Repository navigation
@astrojs/vercel 11.0.13: on-demand routes crash with "Cannot find native binding" (rolldown imported at runtime) #18328
Description
Activity
- addedtriage: in progressAutomated triage is currently runningAutomated triage is currently running
on Oct 9, 2026 Triage complete
- Prepare the workspace: ready
- Install dependencies: complete
- Build the project: complete
- Reproduce the issue: confirmed
- Diagnose the cause: high confidence
- Verify the diagnosis: bug
- Attempt a fix: verified
- Publish the result: set
triage: fix pending
- Reproduced: Yes. Reproduced locally by importing the packaged
_render.funcon its own with@astrojs/vercel@11.0.13. The same project on 11.0.12 works. - Exploration: Yes — View branch
- Unit Test: Yes —
packages/integrations/vercel/test/serverless-prerender.test.ts. This is a fixture build test, not a pure unit test. - Priority: P4: important. This is a regression in a patch release: every on-demand route deployed with
@astrojs/vercel11.0.13 crashes at startup. Pinning to 11.0.12 works around it.
The serverless runtime entry (
packages/integrations/vercel/src/serverless/entrypoint.ts) imports its header and param constants from the integration module../index.js. That module imports./serverless/middleware.js, and since #18263 that file has a top-levelimport { rolldown } from 'rolldown'. The builtentry.mjstherefore ends up withimport "rolldown"(andimport "@vercel/routing-utils"). File tracing doesn't copy rolldown's platform-specific native binding, so the function throws "Cannot find native binding" when it starts.I found a potential fix for this issue. It's the approach you suggested: the shared constants move into a new module with no imports,
src/serverless/constants.ts.entrypoint.tsandmiddleware.tsimport from it, andindex.tsre-exports the constants so the public exports don't change. I rebuilt your repro with the patched adapter:entry.mjsno longer importsrolldownor@vercel/routing-utils, and/ssrreturns 200 from the isolated function copy. This still needs review by a maintainer.Try this fix
You can test this fix right now without waiting for a release:
# @astrojs/vercel npm i https://pkg.pr.new/@astrojs/vercel@f6b984dIf this fixes your issue, please leave a comment letting us know (for example
"confirmed, this fixes it"). A pull request will then be opened to get it merged.Full Triage Report
Issue
Title: @astrojs/vercel 11.0.13: on-demand routes crash with "Cannot find native binding" (rolldown imported at runtime)
Environment (from issue): Astro v7.3.8, Vite v8.3.4, Node v24.18.0, macOS arm64, npm,
@astrojs/vercelv11.0.13.Expected: On-demand routes render on Vercel, as they did with 11.0.12. The serverless runtime should not import build-time-only modules.
Reproduction (reproduced locally, without Vercel)
- Cloned https://github.com/claus/astro-vercel-rolldown-repo, which has one static page and
src/pages/ssr.astrowithprerender = false. Installed@astrojs/vercel@11.0.13andastro@7.3.8with npm. - Ran
npx astro build. The build succeeds. .vercel/output/functions/_render.func/.vercel/output/server/entry.mjscontains:import "@vercel/routing-utils"; import "rolldown";_render.func/node_modules/@rolldown/contains onlypluginutils. No native binding package is copied.cp -R .vercel/output/functions/_render.func /tmp/fn && cd /tmp/fn && node --input-type=module -e "await import('./.vercel/output/server/entry.mjs')"fails with:Error: Cannot find native binding. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ... at file:///tmp/fn/node_modules/rolldown/dist/shared/binding-DlR5d34p.mjs:603:34 cause: Error: Cannot find module '@rolldown/binding-wasm32-wasi'
Baseline: With
@astrojs/vercel@11.0.12,entry.mjsonly hasimport "@vercel/routing-utils";and the isolated import succeeds.Diagnosis (confidence: high)
Import chain:
src/serverless/entrypoint.ts(lines 2-8), the runtimeserverEntrypoint, importsASTRO_LOCALS_HEADER,ASTRO_MIDDLEWARE_SECRET_HEADER,ASTRO_PATH_HEADER,ASTRO_PATH_PARAMandASTRO_PATH_TOKEN_PARAMfrom'../index.js'.src/index.ts(the integration) has top-level imports of@vercel/routing-utils,tinyglobby,@vercel/nft, and./serverless/middleware.js.src/serverless/middleware.ts(line 5) has a top-levelimport { rolldown } from 'rolldown'. This was added in 882dd98, "Replace esbuild with Vite and Rolldown APIs (Replace esbuild with Vite and Rolldown APIs #18263)". Before that, the code used a lazyawait import('esbuild')insidegenerateEdgeMiddleware.- The SSR bundle keeps these packages external. The constants get inlined, but the bare side-effect imports stay in
entry.mjs. NFT copiesrolldownbut not its dynamically resolved native binding, so the function crashes on startup. Prerendered pages are unaffected.
middleware.tsalso imported from../index.js, which created a circular import.@vercel/routing-utilswas already in the runtime bundle in 11.0.12; it is pure JS, so it didn't break anything.Verification: bug (high confidence)
Nothing in #18263, in the source comments, or in the docs suggests that loading rolldown in the deployed function was intended. #18263 swapped the build tooling, and the runtime coupling comes from incidental constant imports.
Fix
- New file with no imports:
packages/integrations/vercel/src/serverless/constants.ts. It holdsASTRO_PATH_HEADER,ASTRO_PATH_PARAM,ASTRO_PATH_TOKEN_PARAM,ASTRO_LOCALS_HEADER,ASTRO_MIDDLEWARE_SECRET_HEADERandNODE_PATH, with their JSDoc moved unchanged. entrypoint.tsandmiddleware.tsimport from./constants.js.index.tsre-exports all six constants, so the public API doesn't change.- The rolldown import was not made lazy. After this change the runtime never reaches
middleware.ts, so it isn't needed.
Verification:
- Repro: Rebuilt the repro with the patched
dist.entry.mjshas norolldownor@vercel/routing-utilsimports,rolldownis no longer copied into the function, anddefault.fetch(new Request('http://localhost/ssr'))returns 200 with the rendered page. - New test: "server entry does not import build-time dependencies" in
serverless-prerender.test.ts. It fails without the fix and passes with it. - Full vercel suite: 88 tests: 85 pass, 0 fail, 3 skipped.
- Checks: Biome and tsc pass with no errors.
Changeset:
.changeset/vercel-runtime-rolldown.md(@astrojs/vercelpatch).--- a/packages/integrations/vercel/src/serverless/entrypoint.ts +++ b/packages/integrations/vercel/src/serverless/entrypoint.ts @@ -5,7 +5,7 @@ import { ASTRO_PATH_HEADER, ASTRO_PATH_PARAM, ASTRO_PATH_TOKEN_PARAM, -} from '../index.js'; +} from './constants.js'; --- a/packages/integrations/vercel/src/serverless/middleware.ts +++ b/packages/integrations/vercel/src/serverless/middleware.ts @@ -10,7 +10,7 @@ import { ASTRO_PATH_TOKEN_PARAM, NODE_PATH, -} from '../index.js'; +} from './constants.js'; --- a/packages/integrations/vercel/src/index.ts +++ b/packages/integrations/vercel/src/index.ts +import { ASTRO_PATH_PARAM, ASTRO_PATH_TOKEN_PARAM, NODE_PATH } from './serverless/constants.js'; +export { + ASTRO_LOCALS_HEADER, + ASTRO_MIDDLEWARE_SECRET_HEADER, + ASTRO_PATH_HEADER, + ASTRO_PATH_PARAM, + ASTRO_PATH_TOKEN_PARAM, + NODE_PATH, +} from './serverless/constants.js'; (constant definitions removed from index.ts, moved to serverless/constants.ts)
Other adapters
Netlify's
src/index.tsalso imports rolldown and esbuild. Its runtime files were not checked in depth, so it was left out of scope.This report was made by an LLM. The analysis may be wrong, and the potential fix might not work, but is intended as a starting point for exploring the issue.
- added- P4: importantViolate documented behavior or significantly impacts performance (priority)Violate documented behavior or significantly impacts performance (priority)pkg: vercelRelated to Vercel adapter (scope)Related to Vercel adapter (scope)triage: fix pendingReporter needs to verify the triage bot fix worksReporter needs to verify the triage bot fix worksand removedtriage: in progressAutomated triage is currently runningAutomated triage is currently running
on Oct 9, 2026 I updated my reproduction project to use
https://pkg.pr.new/@astrojs/vercel@f6b984dand i think that didn't fix it.- addedtriage: fix rejectedReporter says the proposed fix does not workReporter says the proposed fix does not workand removedtriage: fix pendingReporter needs to verify the triage bot fix worksReporter needs to verify the triage bot fix works
on Oct 10, 2026 - added a commit that references this issue
on Oct 11, 2026 I have this issue in my own project too.
https://github.com/Souvlaki42/my-website
Pinning @astrojs/vercel to version 11.0.12 fixes it.
Thanks.- addedtriage: needs triageIssue needs to be triagedIssue needs to be triagedtriage: in progressAutomated triage is currently runningAutomated triage is currently runningand removedtriage: fix rejectedReporter says the proposed fix does not workReporter says the proposed fix does not worktriage: needs triageIssue needs to be triagedIssue needs to be triaged
on Oct 11, 2026 Triage complete
- Prepare the workspace: ready
- Install dependencies: complete
- Build the project: complete
- Reproduce the issue: confirmed
- Diagnose the cause: high confidence
- Verify the diagnosis: bug
- Attempt a fix: verified
- Publish the result: set
triage: fix pending
- Reproduced: Yes. Reproduced locally, without Vercel, by importing the packaged
_render.funcon its own with@astrojs/vercel@11.0.13. The same project on 11.0.12 works. - Exploration: Yes — View branch
- Unit Test: Yes —
packages/integrations/vercel/test/serverless-prerender.test.ts. This is a fixture build test that checks the bundled function entry, not a pure unit test. - Priority: P4: important. This is a regression in a patch release: every on-demand route deployed with
@astrojs/vercel11.0.13 crashes when the function starts. Pinning to 11.0.12 works around it.
The serverless runtime entry (
packages/integrations/vercel/src/serverless/entrypoint.ts) imports its header and param constants from the integration module../index.js. That module imports./serverless/middleware.js, and since #18263 that file has a top-levelimport { rolldown } from 'rolldown'. The builtentry.mjstherefore ends up withimport "@vercel/routing-utils"; import "rolldown";. File tracing doesn't copy rolldown's platform-specific native binding into the function, so importingentry.mjsthrows "Cannot find native binding".I found a potential fix for this issue. It's the approach you suggested:
- The shared constants move into a new module with no imports,
src/serverless/constants.ts. entrypoint.tsandmiddleware.tsimport from it.index.tsre-exports the constants, so the public exports don't change.middleware.tsalso loads rolldown lazily insidegenerateEdgeMiddleware, the way 11.0.12 loaded esbuild.
I rebuilt your repro with the patched adapter.
entry.mjsno longer mentionsrolldownor@vercel/routing-utils, and the isolated function returns 200 for/ssr. A maintainer still needs to review it.@claus: the earlier preview
f6b984dalready removed the rolldown import. When I built your repo from your exact lockfile withnpm ci, the isolated function served/ssrwith 200, even withVERCEL=1and the other Vercel build env vars set. Your live deploy still returns 500, and I can't see Vercel function logs from here, so I don't know why. Could you share the function log from that deployment, and try redeploying without the build cache? That would show whether it was a stale build or a second Vercel-only problem.Try this fix
You can test this fix right now without waiting for a release:
# @astrojs/vercel npm i https://pkg.pr.new/@astrojs/vercel@35a684cIf this fixes your issue, please leave a comment letting us know (for example
"confirmed, this fixes it"). A pull request will then be opened to get it merged.Full Triage Report
Issue
Title: @astrojs/vercel 11.0.13: on-demand routes crash with "Cannot find native binding" (rolldown imported at runtime)
Environment (from issue): Astro v7.3.8, Vite v8.3.4, Node v24.18.0, macOS arm64, npm,
@astrojs/vercelv11.0.13.Expected: On-demand routes render on Vercel, as they did with 11.0.12. The serverless runtime should not import build-only modules.
Reproduction
Sandbox: Linux x86_64, Node v22.23.2, npm 10.9.8. The repro is installed standalone with npm.
- Cloned https://github.com/claus/astro-vercel-rolldown-repo. It has one static page and
src/pages/ssr.astrowithprerender = false. Installed@astrojs/vercel@11.0.13andastro@7.3.8. - Ran
npx astro build. The build succeeds. .vercel/output/functions/_render.func/.vercel/output/server/entry.mjscontains:import "@vercel/routing-utils"; import "rolldown";_render.func/node_modules/@rolldown/contains onlypluginutils.- Imported the function on its own:
It fails with:
cp -R .vercel/output/functions/_render.func /tmp/fn && cd /tmp/fn node --input-type=module -e "await import('./.vercel/output/server/entry.mjs')"Error: Cannot find native binding. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ... at file:///tmp/fn13/node_modules/rolldown/dist/shared/binding-DlR5d34p.mjs:603:34 cause: Error: Cannot find module '@rolldown/binding-wasm32-wasi'
Baseline: With
@astrojs/vercel@11.0.12,entry.mjsonly hasimport "@vercel/routing-utils";. The isolated function handles/ssrwith 200.Preview
f6b984d:entry.mjshas no rolldown or routing-utils import, and the isolated/ssrreturns 200. This also holds with the reporter's exact lockfile (npm ci) and withVERCEL=1,VERCEL_DEPLOYMENT_IDandVERCEL_SKEW_PROTECTION_ENABLEDset. The live deployment still returns500 FUNCTION_INVOCATION_FAILEDon/ssr. The cause is unknown without the function logs.Diagnosis (confidence: high)
src/index.ts:140setsserverEntrypoint: '@astrojs/vercel/entrypoint', which maps todist/serverless/entrypoint.js. This module is bundled into the function.src/serverless/entrypoint.ts:2-8importsASTRO_*constants from'../index.js'.src/index.tshas top-level imports of build-only modules:@vercel/routing-utils,tinyglobby,./lib/nft.jsand./serverless/middleware.js.src/serverless/middleware.ts:5has a top-levelimport { rolldown } from 'rolldown', added in882dd98cd(Replace esbuild with Vite and Rolldown APIs #18263). Before that, it loaded esbuild with a lazyawait import('esbuild').- The SSR build keeps npm packages external. The constants get inlined, but the bare side-effect imports stay in the bundle. At runtime rolldown loads its native binding dynamically, NFT can't trace it, and the function crashes on import.
Verification: bug (high confidence)
- This is a regression in a patch release. The changeset for Replace esbuild with Vite and Rolldown APIs #18263 describes it as an internal refactor.
- The coupling between the runtime and
index.tsdates from 2024. No comment or code shows it was intended, and it was harmless until a native-binding package was imported at the top level. - A second user reports the same problem.
Fix
- New
src/serverless/constants.tswith no imports. It holdsASTRO_PATH_HEADER,ASTRO_PATH_PARAM,ASTRO_PATH_TOKEN_PARAM,ASTRO_LOCALS_HEADER,ASTRO_MIDDLEWARE_SECRET_HEADERandNODE_PATH, moved verbatim with their docs. entrypoint.tsandmiddleware.tsimport from./constants.js. This also removes the circularmiddleware.ts→index.tsimport.index.tsimports and re-exports the constants, so the public API is unchanged.middleware.tsloads rolldown lazily insidegenerateEdgeMiddleware(const { rolldown } = await import('rolldown')).- Changeset:
.changeset/vercel-runtime-no-rolldown.md(@astrojs/vercel: patch).
Fix verification
- I packed the patched adapter and installed it into a copy of the reporter's repro.
- The function
entry.mjshas 0 occurrences ofrolldown, andnode_modulesno longer contains rolldown or@vercel/*. - The isolated
/ssrreturns 200. - Full vercel suite: 88 tests, 85 pass, 0 fail, 3 pre-existing skips. This includes the edge-middleware and ISR edge-middleware tests, which use rolldown.
- Biome, tsc and eslint are clean.
Test
it('server entry does not import build-only dependencies')intest/serverless-prerender.test.tsreads the_render.funchandler named in.vc-config.json. It asserts the handler has no"rolldown"or"@vercel/routing-utils"import. Without the fix it fails, because the entry containsimport "@vercel/routing-utils";\nimport "rolldown";. With the fix it passes.Alternatives considered
- Only lazy-loading rolldown: this fixes the crash, but the runtime would still bundle the integration module and
@vercel/routing-utils. - sideEffects/externals config: indirect and fragile compared with removing the import.
This report was made by an LLM. The analysis may be wrong, and the potential fix might not work, but is intended as a starting point for exploring the issue.
- addedtriage: fix pendingReporter needs to verify the triage bot fix worksReporter needs to verify the triage bot fix worksand removedtriage: in progressAutomated triage is currently runningAutomated triage is currently running
on Oct 11, 2026 Confirmed, this fixes it.
Vercel's build cache was indeed hanging on to the buggy package.
- addedtriage: fix verifiedReporter confirmed the triage bot fix worksReporter confirmed the triage bot fix worksand removedtriage: fix pendingReporter needs to verify the triage bot fix worksReporter needs to verify the triage bot fix works
on Oct 11, 2026 The fix has been verified! A pull request has been created: #18339
Astro Info
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
Since
@astrojs/vercel11.0.13, every on-demand route deployed to Vercel fails with500 FUNCTION_INVOCATION_FAILED. Prerendered pages are unaffected. The function log shows:The generated server entry (entry.mjs) now contains
import "rolldown";. This seems to come from #18263 ("Replace esbuild with Vite and Rolldown APIs"):dist/serverless/entrypoint.js, the runtime, imports constants such asASTRO_PATH_HEADERfrom../index.js.dist/index.js, the integration, imports./serverless/middleware.js.serverless/middleware.jshas a top-levelimport { rolldown } from "rolldown". In 11.0.12 it used a lazyawait import("esbuild")inside the function.So rolldown now gets loaded inside the function. Its platform-specific native binding is loaded dynamically, so file tracing doesn't copy it into the function: only
@rolldown/pluginutilsends up innode_modules/@rolldown. The function crashes on start-up.It also reproduces locally without Vercel, by importing the packaged function in isolation:
Pinning
@astrojs/vercelto 11.0.12 fixes it.Repro:
https://github.com/claus/astro-vercel-rolldown-repo
https://astro-vercel-rolldown-repo.vercel.app/
What's the expected result?
On-demand routes render on Vercel, as with 11.0.12. The serverless runtime entry should not import build-time-only modules such as
rolldownand@vercel/routing-utils. The shared constants could, for example, move into a small module with no build dependencies, which bothindex.jsandentrypoint.jsimport.Link to Minimal Reproducible Example
https://github.com/claus/astro-vercel-rolldown-repo
Participation