Hi all,
I’m encountering a persistent runtime error when trying to generate PDFs using Puppeteer within a Next.js App Router project deployed on Vercel. The PDF generation works correctly in my local development environment but fails consistently on Vercel deployments.
Project Details:
- **Project Name: Vectorcv
- Framework: Next.js (App Router)
- Node.js Runtime: Node 22.x (as per deployment logs)
- **error from vercel
Error in PDF generation: Error: The input directory "/var/task/.next/server/bin" does not exist.
at d.executablePath (/var/task/.next/server/chunks/191.js:1:64134)
at l (/var/task/.next/server/app/api/pdf/route.js:1:1697)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async u (/var/task/.next/server/app/api/pdf/route.js:1:4235)
at async /var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:38411
at async e_.execute (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:27880)
at async e_.handle (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:39943)
at async en (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:16:25516)
at async ea.responseCache.get.routeKind (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:1028)
at async r9.renderToResponseWithComponentsImpl (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:508)
Error in PDF API route: Error: Failed to generate PDF: The input directory "/var/task/.next/server/bin" does not exist.
at l (/var/task/.next/server/app/api/pdf/route.js:1:3486)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async u (/var/task/.next/server/app/api/pdf/route.js:1:4235)
at async /var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:38411
at async e_.execute (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:27880)
at async e_.handle (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:39943)
at async en (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:16:25516)
at async ea.responseCache.get.routeKind (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:1028)
at async r9.renderToResponseWithComponentsImpl (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:508)
at async r9.renderPageComponent (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:5102)
Problem Description: The /api/pdf
serverless function is designed to generate a PDF from HTML content using puppeteer-core
and @sparticuz/chromium-min
. While this works locally, on Vercel it fails with the following runtime error logged in the function logs:
Error: Failed to generate PDF: The input directory "/var/task/.next/server/bin" does not exist.
at d.executablePath (/var/task/.next/server/chunks/191.js:1:64134)
at l (/var/task/.next/server/app/api/pdf/route.js:1:1697)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async u (/var/task/.next/server/app/api/pdf/route.js:1:4235)
... (rest of stack trace) ...
This indicates that the necessary Chromium binary files provided by @sparticuz/chromium-min
are not being found at the expected path within the Vercel runtime environment.
Troubleshooting Steps Taken:
- Dependencies: Confirmed use of
puppeteer-core
and@sparticuz/chromium-min
(switched from the full@sparticuz/chromium
in an attempt to resolve). - Dynamic Imports: Implemented dynamic imports (
await import(...)
) for bothpuppeteer-core
and@sparticuz/chromium-min
within the service function (lib/services/pdf.service.ts
) that handles PDF generation. This successfully reduced the reported Vercel function size from ~68MB to ~7MB, suggesting the initial bundle size limit is not the issue. next.config.mjs
Configurations: Tried various configurations, including:
- The recommended setup:
experimental: { serverComponentsExternalPackages: ['@sparticuz/chromium-min'], outputFileTracingIncludes: { '/api/pdf': ['./node_modules/@sparticuz/chromium-min/**'] } }
- Using more specific paths in
outputFileTracingIncludes
(e.g., targeting thebin
directory). - Removing
@sparticuz/chromium-min
fromserverComponentsExternalPackages
. - Removing
outputFileTracingIncludes
entirely. - Using
@vercel/nft
’swithFileTracing
helper. - Removing the entire
experimental
block related to tracing/externals. None of these configuration changes resolved the runtime path error.
- Environment Variables: Added
SPARTICUZ_FUNCTION_NAME=pdf-generator
to Vercel environment variables based on troubleshooting guides. Confirmed other potentially conflicting variables likePUPPETEER_EXECUTABLE_PATH
are not set. - Code Structure: The API route (
app/api/pdf/route.tsx
) simply imports and calls a service function (lib/services/pdf.service.ts
). The service function contains the dynamic imports and Puppeteer logic, correctly callingawait chromium.executablePath()
.
Despite these steps, the runtime error persists across deployments. It seems like an issue with Vercel’s build process not correctly tracing or packaging the necessary binary files from @sparticuz/chromium-min
into the expected runtime location (/var/task/.next/server/bin
or similar path resolved by chromium.executablePath()
).
Could you please provide guidance on how to resolve this file tracing/packaging issue for @sparticuz/chromium-min
within the Vercel environment?
also having @sparticuz/chromium-min has helped me keep this under 50MB limit
any assistance will be greatly appreciated. thank you.