javascriptreactjsnext.jsnext.js13airtable

TypeError: Cannot read properties of undefined when making AirTable API call with NextJS 13.4


I'm learning the new App router using NextJS 13.4 and have come across an error when attempting to make an external api call.

I actually receive all of the data properly from Airtable but because Next throws this error it causes my try catch to break. I cannot for the life of me figure out what is throwing this error and how to fix it.

Here is the error it is throwing:

- error TypeError: Cannot read properties of undefined (reading 'headers')
    at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:254:61)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

I am making the initial call from a client component located at /app/dashboard/page.js.

page.js looks something like this:

'use client'

import React, { useEffect } from 'react';

const Dashboard = () => {

  useEffect(() => {

    async function fetchData() {
      try {
        const res = await fetch('/api/jobs', {
          method: 'GET',
          headers: {
            'id': '123'
          }
        });

        const data = await res.json();
        console.log("hello", data); // I never hit this console log because the catch below catches the error

      } catch (error) {
        console.log("error")
        console.log(error);
      }
    };

    fetchData();
  }, []);
  
  return (
    <div>
      Hello World
    </div>
  );
}

export default Dashboard;

Then I have my handler located at /app/api/jobs/route.js

route.js looks something like this:

import { NextResponse } from 'next/server';
import { jobs } from "../../../utils/Airtable";
 
export async function GET(req) {

  let headers = await req.headers.get('id'); // this logs out the headers just fine

  let recordsArr = [];

  try {
        jobs.select({
            view: 'Grid view',
            fields: ['Project Lead'],
            filterByFormula: `AND({Project Lead} = 'Jane Doe', AND({Created Day}, '6/1/23'))`
        }).eachPage(function page(records, fetchNextPage) {
                recordsArr.push(...records);
                
                try {
                    fetchNextPage();
                } catch (err) {
                    console.log(err)
                    return;
                };
            }, function done(err) { 

                if (err) {
                    return new NextResponse(JSON.stringify({message: 'Error'})) 
                };

                console.log(recordsArr) // this logs out the records perfectly
                return new NextResponse(JSON.stringify(recordsArr));
        });

    } catch (err) {

        return new NextResponse(JSON.stringify({message: 'Error'}), { status: 500 })

    };

  return new NextResponse(JSON.stringify(obj), { status: 200 });
}

As soon as I comment out the Airtable api call I stop getting the error.

If I move the entire Airtable API call to the client component it works flawlessly. So I think there is something about NextJS that I'm not comprehending.

Appreciate your time.


Solution

  • I empathize with your situation as I faced the exact same issue a while ago. It took me a couple of hours to pinpoint the problem, but eventually I found the solution.

    The issue with your code is the unnecessary use of the new keyword in your return statement. You're currently using this line:

    return new NextResponse(JSON.stringify(recordsArr));
    

    So, what you should be doing instead is:

    return NextResponse(JSON.stringify(recordsArr));
    

    In my case, removing the new keyword was enough to resolve the issue.

    If you're still having trouble, it could be beneficial to debug with a smaller piece of code or to isolate different parts of your code to pinpoint where the problem is originating from.

    I hope this resolves your issue!