Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"SyntaxError: Unexpected token < in JSON at position 0" on production build

Tags:

next.js

vercel

I've been trying to figure this out for the past week. I can't find an answer or think of a reasonable explanation as to why everything works when I'm developing on localhost, but things constantly fail to build on Vercel.

So I'm using Next 13.4.12 and I have everything set up as follows:

  • app/projects/page.tsx
  • app/api/projects/route.ts

Here is the code:

const ProjectList = async () => {
  const baseUrl =
    process.env.NODE_ENV === "development"
      ? "http://localhost:3000"
      : "https://www.example.com";

  const response = await fetch(`${baseUrl}/api/projects`);
  const data = await response.json();
  const projects: Project[] = data.projects;

  return (
    <div>
      {projects?.map((project) => <h1>{project?.name}</h1>)} // etc. etc.
    </div>
  );
};
export async function GET() {
    try {
      // Retrieve the "projects" collection from Firestore
      const projectsCollection = collection(db, "projects");
      const projectsSnapshot = await getDocs(projectsCollection);

      // Map the documents in the collection to an array of project objects
      const projects = projectsSnapshot.docs.map((doc) => ({
        id: doc.id,
        ...doc.data(),
      }));

      return NextResponse.json(JSON.stringify({ projects: projects }));
    } catch (error) {
      console.error("Error retrieving projects:", error);
      return NextResponse.error();
    }
}

I've tried with and without JSON.stringify. Everything works as I'd expect when on localhost. But when trying to deploy to Vercel I get the following error:

SyntaxError: Unexpected token < in JSON at position 0
11:13:00.318        at JSON.parse (<anonymous>)
11:13:00.318        at parseJSONFromBytes (node:internal/deps/undici/undici:6571:19)
11:13:00.318        at successSteps (node:internal/deps/undici/undici:6545:27)
11:13:00.319        at node:internal/deps/undici/undici:1211:60
11:13:00.319        at node:internal/process/task_queues:140:7
11:13:00.319        at AsyncResource.runInAsyncScope (node:async_hooks:203:9)
11:13:00.319        at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8)
11:13:00.319        at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
11:13:00.336    
11:13:00.336    Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
11:13:00.336    SyntaxError: Unexpected token < in JSON at position 0
11:13:00.336        at JSON.parse (<anonymous>)
11:13:00.336        at parseJSONFromBytes (node:internal/deps/undici/undici:6571:19)
11:13:00.337        at successSteps (node:internal/deps/undici/undici:6545:27)
11:13:00.340        at node:internal/deps/undici/undici:1211:60
11:13:00.340        at node:internal/process/task_queues:140:7
11:13:00.340        at AsyncResource.runInAsyncScope (node:async_hooks:203:9)
11:13:00.340        at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8)
11:13:00.340        at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
11:13:00.340    
11:13:00.340    > Export encountered errors on following paths:
11:13:00.340        /page: /
11:13:00.340    - info Generating static pages (5/5)
11:13:00.398    Error: Command "npm run build" exited with 1

Please help as it's driving me insane! Thank you!

I've tried reading the documentation, watching Youtube videos, etc. but can't really find anything relevant to the new app router using api.

like image 446
PP24 Avatar asked Aug 31 '25 01:08

PP24


1 Answers

This error occurs if you try to call your internal API route from a server component at build time, where there is no application running (the application being build and not deployed yet). Tim Neutkens from Next.js points that out on a GitHub issue with a similar error:

This is because you're trying to fetch from an internal api route during build, which is not supported.

Instead of calling the internal API route from a server component, which then calls your DB or CMS, reach them directly from the component. It helps avoid the error, and also an additional useless API call.

const ProjectList = async () => {
  const projectsCollection = collection(db, "projects");
  const projectsSnapshot = await getDocs(projectsCollection);

  // Map the documents in the collection to an array of project objects
  const projects = projectsSnapshot.docs.map((doc) => ({
    id: doc.id,
    ...doc.data(),
  }));

  return (
    <div>
      {projects.map((project, idx) => (
        <h1 key={idx}>{project?.name}</h1>
      ))}
    </div>
  );
};
like image 107
yousoumar Avatar answered Sep 02 '25 16:09

yousoumar