How Do Fix the ‘Error Serializing .res’ in Next.js getServerSideProps?

When I first started working with Next.js and the Binance API, I ran into a frustrating error that stopped my project in its tracks. The error looked like this:

Error serializing `.res` returned from `getServerSideProps` in "/dashboard".
Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.

At first, I wasn’t sure what this meant. But after some debugging, I realized the root cause: Next.js requires that everything returned from getServerSideProps must be JSON serializable. That means no undefined, no Error objects, no functions, and no complex classes just plain objects, arrays, strings, numbers, booleans, or null.

Let me walk you through the problem, the fix, and how I improved my code along the way.

The Broken Code

Here’s the first version of my code:

import binance from "../config/binance-config";

export async function getServerSideProps() {
  const res = await binance.balance((error, balances) => {
    console.info("BTC balance: ", balances.BTC.available);
  });

  return {
    props: {
      res,
    },
  };
}

The issue is that binance.balance is callback-based. It doesn’t actually return anything. I was trying to await a function that doesn’t support promises, so res became undefined. And when Next.js tried to serialize undefined into JSON, it blew up with that error.

The Fix Version

To solve this, I wrapped the Binance callback in a Promise, so I could use it with await and safely pass plain JSON to my React component.

// pages/dashboard.js
import binance from "../config/binance-config";

export async function getServerSideProps() {
  try {
    // Wrap callback in a Promise
    const balances = await new Promise((resolve, reject) => {
      binance.balance((error, data) => {
        if (error) return reject(error);
        resolve(data);
      });
    });

    // Extract just the BTC balance
    const btc = {
      available: balances?.BTC?.available ?? null,
      onOrder: balances?.BTC?.onOrder ?? null,
    };

    return {
      props: {
        btc, // serializable
      },
    };
  } catch (err) {
    return {
      props: {
        btc: null,
        error: err.message || "Something went wrong",
      },
    };
  }
}

export default function Dashboard({ btc, error }) {
  if (error) return <p>Error: {error}</p>;
  if (!btc) return <p>No BTC data found.</p>;

  return (
    <div>
      <h1>Dashboard</h1>
      <p>BTC Available: {btc.available}</p>
      <p>BTC On Order: {btc.onOrder}</p>
    </div>
  );
}

My Binance Config

I also cleaned up my API keys by moving them into .env.local:

// config/binance-config.js
import Binance from "node-binance-api";

const binance = new Binance().options({
  APIKEY: process.env.BINANCE_API_KEY,
  APISECRET: process.env.BINANCE_API_SECRET,
});

export default binance;

And in .env.local:

BINANCE_API_KEY=your_api_key
BINANCE_API_SECRET=your_api_secret

This way, I don’t risk pushing secrets to GitHub by mistake.

Extra Practice Functionality

Once I had BTC working, I wanted to make my dashboard more useful. Instead of just showing Bitcoin, I extended it to display multiple coins in a table.

Fetching Multiple Coins

const selectedCoins = ["BTC", "ETH", "BNB"];
const filteredBalances = selectedCoins.map((coin) => ({
  symbol: coin,
  available: balances?.[coin]?.available ?? null,
  onOrder: balances?.[coin]?.onOrder ?? null,
}));

return {
  props: {
    balances: filteredBalances,
  },
};

Displaying the Data in a Table

export default function Dashboard({ balances }) {
  if (!balances) return <p>No balances found.</p>;

  return (
    <div>
      <h1>My Balances</h1>
      <table>
        <thead>
          <tr>
            <th>Coin</th>
            <th>Available</th>
            <th>On Order</th>
          </tr>
        </thead>
        <tbody>
          {balances.map((b) => (
            <tr key={b.symbol}>
              <td>{b.symbol}</td>
              <td>{b.available}</td>
              <td>{b.onOrder}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

Now I can see all my selected coin balances in a clean table whenever I load the dashboard page.

Final Thought

Running into serialization errors in Next.js can be frustrating, but the fix is usually straightforward once you remember that only plain JSON is allowed in props. By wrapping the Binance API in a Promise and carefully structuring the data I return, I not only solved the error but also built a functional crypto dashboard.

This project started as a small debugging exercise, but it became a neat little playground where I can fetch and display my balances in real time. The best part? I now feel much more confident handling server side rendering and API integration in Next.js.

Related blog posts