vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.55k stars 26.92k forks source link

Route handler returns 404 instead of 200 #58459

Open moroshko opened 11 months ago

moroshko commented 11 months ago

Link to the code that reproduces this issue

https://github.com/moroshko/nextjs-pdfmake-issue

To Reproduce

  1. git clone https://github.com/moroshko/nextjs-pdfmake-issue.git
  2. cd nextjs-pdfmake-issue
  3. bun i
  4. bun dev
  5. Visit http://localhost:3000/api/hello

Current vs. Expected behavior

Expected: 200 Actual: 404

Verify canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 22.6.0: Fri Sep 15 13:39:52 PDT 2023; root:xnu-8796.141.3.700.8~1/RELEASE_X86_64
Binaries:
  Node: 18.17.0
  npm: 9.6.7
  Yarn: 1.22.19
  pnpm: N/A
Relevant Packages:
  next: 14.0.3-canary.8
  eslint-config-next: 14.0.3-canary.8
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.2.2
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

App Router, Middleware / Edge (API routes, runtime)

Additional context

The following route handler returns a 404 when navigating to http://localhost:3000/api/hello:

app/api/hello/route.ts

import PdfPrinter from "pdfmake";

export async function GET() {
  try {
    const printer = new PdfPrinter({});

    return Response.json({ message: "ok" });
  } catch (error) {
    return Response.json({ error: "something went" });
  }
}

Commenting out const printer = new PdfPrinter({}); solves the issue (200 is returned, as expected).

Here is the 404 response body:

<!DOCTYPE html>
<html id="__next_error__">
    <head>
        <meta charSet="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack.js"/>
        <script src="/_next/static/chunks/main-app.js" async=""></script>
        <script src="/_next/static/chunks/app-pages-internals.js" async=""></script>
        <meta name="robots" content="noindex"/>
        <meta name="next-error" content="not-found"/>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app"/>
        <meta name="next-size-adjust"/>
        <script src="/_next/static/chunks/polyfills.js" noModule=""></script>
    </head>
    <body>
        <script src="/_next/static/chunks/webpack.js" async=""></script>
        <script>
            (self.__next_f = self.__next_f || []).push([0]);
            self.__next_f.push([2, null])
        </script>
        <script>
            self.__next_f.push([1, "1:HL[\"/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/_next/static/css/app/layout.css?v=1700007430527\",\"style\"]\n0:\"$L3\"\n"])
        </script>
        <script>
            self.__next_f.push([1, "4:I[\"(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js\",[\"app-pages-internals\",\"static/chunks/app-pages-internals.js\"],\"\"]\n6:I[\"(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js\",[\"app-pages-internals\",\"static/chunks/app-pages-internals.js\"],\"\"]\n7:I[\"(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js\",[\"app-pages-internals\",\"static/chunks/app-pages-internals.js\"],\"\"]\n8:I[\"(app-pages-browser)/./node_modules/next/dist/clien"])
        </script>
        <script>
            self.__next_f.push([1, "t/components/render-from-template-context.js\",[\"app-pages-internals\",\"static/chunks/app-pages-internals.js\"],\"\"]\n"])
        </script>
        <script>
            self.__next_f.push([1, "3:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/app/layout.css?v=1700007430527\",\"precedence\":\"next_static/css/app/layout.css\",\"crossOrigin\":\"$undefined\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"development\",\"assetPrefix\":\"\",\"initialCanonicalUrl\":\"/api/hello\",\"initialTree\":[\"\",{\"children\":[\"__DEFAULT__\",{}]},\"$undefined\",\"$undefined\",true],\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$L5\"],\"globalErrorComponent\":\"$6\",\"children\":[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_e66fe9\",\"children\":[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"loading\":\"$undefined\",\"loadingStyles\":\"$undefined\",\"loadingScripts\":\"$undefined\",\"hasLoading\":false,\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[],\"childProp\":{\"current\":[\"$L9\",\"$La\",null],\"segment\":\"__DEFAULT__\"},\"styles\":null}]}]}],null]}]]\n"])
        </script>
        <script>
            self.__next_f.push([1, "a:E{\"digest\":\"NEXT_NOT_FOUND\",\"message\":\"NEXT_NOT_FOUND\",\"stack\":\"Error: NEXT_NOT_FOUND\\n    at notFound (webpack-internal:///(rsc)/./node_modules/next/dist/client/components/not-found.js:23:19)\\n    at NoopParallelRouteDefault (webpack-internal:///(rsc)/./node_modules/next/dist/client/components/parallel-route-default.js:13:28)\\n    at eO (/Users/mishamoroshko/temp/nextjs-pdfmake-issue/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:261871)\\n    at /Users/mishamoroshko/temp/nextjs-pdfmake-issue/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:274673\\n    at Array.toJSON (/Users/mishamoroshko/temp/nextjs-pdfmake-issue/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:279443)\\n    at stringify (\u003canonymous\u003e)\\n    at /Users/mishamoroshko/temp/nextjs-pdfmake-issue/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:265799\\n    at ez (/Users/mishamoroshko/temp/nextjs-pdfmake-issue/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:265878)\\n    at eH (/Users/mishamoroshko/temp/nextjs-pdfmake-issue/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:266279)\\n    at Timeout._onTimeout (/Users/mishamoroshko/temp/nextjs-pdfmake-issue/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:262777)\\n    at listOnTimeout (node:internal/timers:569:17)\\n    at process.processTimers (node:internal/timers:512:7)\"}\n"])
        </script>
        <script>
            self.__next_f.push([1, "5:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"Create Next App\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"Generated by create next app\"}],[\"$\",\"meta\",\"4\",{\"name\":\"next-size-adjust\"}]]\n9:null\n"])
        </script>
        <script>
            self.__next_f.push([1, ""])
        </script>
    </body>
</html>

NEXT-3259

Asifdecoder commented 11 months ago

Hi I have fixed the issue please check and review : https://github.com/moroshko/nextjs-pdfmake-issue/pull/1

showonne commented 11 months ago

experiencing the same issue

lmyslinski commented 11 months ago

Same issue here. Trying to use pdfmake on the server-side makes the route return 404 instead of 200. Here's the route:

import { writePDF } from "@/src/template/server-side";
import { NextResponse } from "next/server";

export const dynamic = "force-dynamic";

export async function GET(
  request: Request, // do not remove
  { params }: { params: { uuid: string } }
) {
  // writePDF();
  return new NextResponse("OK");
}

This is one big WTF. This doesn't brake on import, but when the function call is uncommented. But the function is never called, since the route automatically goes to 404. There is 0 errors whatsoever.

I can successfully run the function defined in @/src/template/server-side via ts-node. This only breaks in Next.js

@Asifdecoder You've literally just removed the function invocation in that PR and you call that a fix?

lmyslinski commented 11 months ago

Did some more digging and found out that next build produces an error instead of just swallowing it into a 404:

~/dir/web (h2b-layout ✗) pnpm run build

> web@0.1.0 build dir/web
> next build

   ▲ Next.js 14.0.3
   - Environments: .env

 ✓ Creating an optimized production build
 ✓ Compiled successfully
 ✓ Linting and checking validity of types
   Collecting page data  ..Error: ENOENT: no such file or directory, open 'dir/web/.next/server/app/api/[uuid]/generate/data.trie'
    at Object.openSync (node:fs:603:3)
    at Object.readFileSync (node:fs:471:35)
    at 22318 (dir/web/.next/server/app/api/[uuid]/generate/route.js:1:101599)
    at t (dir/web/.next/server/webpack-runtime.js:1:143)
    at 96985 (dir/web/.next/server/app/api/[uuid]/generate/route.js:1:234192)
    at t (dir/web/.next/server/webpack-runtime.js:1:143)
    at 50301 (dir/web/.next/server/app/api/[uuid]/generate/route.js:14:202634)
    at t (dir/web/.next/server/webpack-runtime.js:1:143)
    at 40620 (dir/web/.next/server/app/api/[uuid]/generate/route.js:14:202784)
    at t (dir/web/.next/server/webpack-runtime.js:1:143) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: 'dir/web/.next/server/app/api/[uuid]/generate/data.trie'
}

> Build error occurred
Error: Failed to collect page data for /api/[uuid]/generate
    at dir/web/node_modules/.pnpm/next@14.0.3_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:1217:15
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  type: 'Error'
}
   Collecting page data  . ELIFECYCLE  Command failed with exit code 1.

Which in turn has lead here to this PDFKit issue: https://github.com/bpampuch/pdfmake/issues/2455

Which then leads to a 4 year old webpack example... this is still a bug on Next.js side, as a route compilation failure should not go to a 404, but to fix our problem with pdfmake seems like we're gonna need a custom webpack

lmyslinski commented 11 months ago

@moroshko If you're interested I have a working sample for client-side, was going for server-side as it's much easier to get custom fonts done

jimmysafe commented 10 months ago

Same issue here using nextjs@14 route handlers.

import PdfMake from "pdfmake";

export async function GET() {
  const pdfMake = new PdfMake({});
  console.log(pdfMake);
  return Response.json({ data: "ok" });
}

This will return a 404 page on nextjs. However if i remove const pdfMake = new PdfMake({}); the route handlers correctly displays the json response. At this point i feel like this is a problem with nextjs.

Let's hope this gets fixed asap.

seungjulee commented 10 months ago

I'm getting the same error when I try to call a grpc service client. This is a bizarre error. Please fix this!

la289 commented 9 months ago

Has anyone gotten this to work?

jimmysafe commented 9 months ago

+1

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

ddm50 commented 7 months ago

Anyone has an idea? I'm getting this issue with @project-serum/anchor

michal-markiewicz commented 7 months ago

I had same issue with importing pdf-parse package, api routes were returning 404 with no error in the console whatsoever. Finally I thought of trying to 'next build' and then error came up. This is terrible for debugging, why shouldn't those error come up in dev?

EmmanuelOta commented 6 months ago

I had same issue with importing pdf-parse package, api routes were returning 404 with no error in the console whatsoever. Finally I thought of trying to 'next build' and then error came up. This is terrible for debugging, why shouldn't those error come up in dev?

Please how did you fix this, I'm having the same error right now with pdf-parse

napter commented 6 months ago

If anyone has figured out how to get past this error in next.js, I would appreciate the info.

ddm50 commented 6 months ago

If anyone has figured out how to get past this error in next.js, I would appreciate the info.

This happens because the package you use, or function throws an error, but Next js does not actually show the error and just returns 200 for some odd reason. Maybe that helps you.

EmmanuelOta commented 6 months ago

If anyone has figured out how to get past this error in next.js, I would appreciate the info.

This happens because the package you use, or function throws an error, but Next js does not actually show the error and just returns 200 for some odd reason. Maybe that helps you.

Hello, sorry for the late reply, just seeing this. I actually just decided to do the whole extraction thing on an express api with pdf-parse. Works perfectly

ddm50 commented 6 months ago

If anyone has figured out how to get past this error in next.js, I would appreciate the info.

This happens because the package you use, or function throws an error, but Next js does not actually show the error and just returns 200 for some odd reason. Maybe that helps you.

Hello, sorry for the late reply, just seeing this. I actually just decided to do the whole extraction thing on an express api with pdf-parse. Works perfectly

well yeah express does work. just wonder why next js throws a 200 when theres an error and shows no error. very stupid.

EmmanuelOta commented 6 months ago

If anyone has figured out how to get past this error in next.js, I would appreciate the info.

This happens because the package you use, or function throws an error, but Next js does not actually show the error and just returns 200 for some odd reason. Maybe that helps you.

Hello, sorry for the late reply, just seeing this. I actually just decided to do the whole extraction thing on an express api with pdf-parse. Works perfectly

well yeah express does work. just wonder why next js throws a 200 when theres an error and shows no error. very stupid.

Haha, the life :)

timneutkens commented 6 months ago

Did some digging into this, the reason it happens is that the library throw an error in the module scope, specifically it's a file reading error where error.code is 'ENOENT'. In Next.js we handle error.code === 'ENOENT' for legacy reasons, specifically backwards compat with older versions of Next.js. A simplified reproduction is this:

// app/api/hello/route.js
const err = new Error("test");
err.code = "ENOENT";
throw err;

export async function GET() {
  try {
    return Response.json({ message: "ok" });
  } catch (error) {
    return Response.json({ error: "something went" });
  }
}

The reason it happens with:

import PdfPrinter from "pdfmake";

export async function GET() {
  try {
    const printer = new PdfPrinter({});
    return Response.json({ message: "ok" });
  } catch (error) {
    return Response.json({ error: "something went" });
  }
}

But doesn't happen with:

import PdfPrinter from "pdfmake";

export async function GET() {
  try {
    // const printer = new PdfPrinter({});
    return Response.json({ message: "ok" });
  } catch (error) {
    return Response.json({ error: "something went" });
  }
}

Is that webpack will shake the pdfmake import as it's unused, so the error doesn't happen as the code doesn't run.

Because of that another way to reproduce is just logging the package without using it any other way:

import PdfPrinter from "pdfmake";
console.log(PdfPrinter)

export async function GET() {
  try {
    return Response.json({ message: "ok" });
  } catch (error) {
    return Response.json({ error: "something went" });
  }
}

Will check with the team what the best way forward is, in some other places the code is stripped when it's know to be application code.

EmmanuelOta commented 6 months ago

Ahhhh, I see... I guess you guys would have to fix the way web pack handles it then. Thanks for the clarification.

Anderson-Pozo commented 5 months ago

I have the same problem, has anyone found a solution yet?

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

edw19 commented 5 months ago

I have the same issue

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

aprilmintacpineda commented 4 months ago

I'm currently getting this error and stuck. I can't find a solution.

I literally just have this:

src/app/webhooks/paddle/route.ts

export async function POST() {
  console.log('paddle webhook');
}

I even tried changing it to GET too, but every time I send a request to localhost:3000/webhooks/paddle I get 404 and I don't see the log.

EDIT:

I tried adding a GET handler in there and then opened endpoint in chrome, to my amusement it worked. However, when I tried to send a GET request to the same endpoint using postman, it fails with 404 error.

I tried deploying it on vercel, and I can see that hitting the endpoint returns 404

image

EDIT:

Figured it out, it's because of middleware.ts, weird part is, I don't know why it's returning 404, because it should have returned something else.

hellokai55 commented 4 months ago

https://stackoverflow.com/questions/76424198/why-do-pdf-parsing-libraries-pdf2json-and-pdf-parse-seem-to-not-work-with-next-j

i use this code, it's work

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["pdf-parse"],
  },
};

module.exports = nextConfig;
vmnog commented 3 months ago

https://stackoverflow.com/questions/76424198/why-do-pdf-parsing-libraries-pdf2json-and-pdf-parse-seem-to-not-work-with-next-j

i use this code, it's work

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["pdf-parse"],
  },
};

module.exports = nextConfig;

This solved the issue, thank you!