nextjs - ✅(Solved) Fix proxy/middleware does not work with ESM only app when deployed to vercel [1 pull requests, 6 comments, 6 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#86434Fetched 2026-04-08 02:11:03
View on GitHub
Comments
6
Participants
6
Timeline
19
Reactions
0
Timeline (top)
commented ×6subscribed ×4labeled ×3referenced ×2

Error Message

ESM-only should be supported on proxy/middleware too. Instead, I get the error this error from the application logs: Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/apps/web/.next/server/middleware.js from /var/task/apps/web/___next_launcher.cjs not supported. Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/apps/web/.next/server/middleware.js from /var/task/apps/web/___next_launcher.cjs not supported.

Fix Action

Fixed

PR fix notes

PR #8: Support ESM-only projects for proxy/middleware loading

Description (problem / solution / changelog)

What?

Adds support for ESM-only projects in proxy and middleware loading by dynamically importing ESM modules using import(). Introduces a method to detect ESM environments and ensures compatibility with Windows paths. Includes a new test suite for ESM-only projects.

Why?

To improve the framework's compatibility with projects that use ESM exclusively.

How?

  • Implemented isESMProject() to detect ESM environments via package.json.
  • Updated loadNodeMiddleware() to use dynamic import for ESM projects.
  • Transformed Windows paths using pathToFileURL() for proper ESM imports.
  • Added test cases to ensure ESM-only proxy middleware functionality.

Fixes #86434

Changed files

  • packages/next/src/server/next-server.ts (modified, +45/-7)
  • test/e2e/app-dir/app-middleware-proxy-esm/app-middleware-proxy-esm.test.ts (added, +28/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/app/api/test/route.js (added, +5/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/app/layout.js (added, +7/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/app/page.js (added, +3/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/app/rewritten/page.js (added, +3/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/next.config.js (added, +6/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/package.json (added, +3/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/proxy.js (added, +24/-0)

Code Example

Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/apps/web/.next/server/middleware.js from /var/task/apps/web/___next_launcher.cjs not supported.
middleware.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead either rename middleware.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /var/task/apps/web/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

    at /opt/rust/nodejs.js:2:13527
    at Function.Jr (/opt/rust/nodejs.js:2:13905)
    at Ue.e.<computed>.Be._load (/opt/rust/nodejs.js:2:13497)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14) {
  code: 'ERR_REQUIRE_ESM'
}
Node.js process exited with exit status: 1. The logs above can help with debugging the issue.
Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/apps/web/.next/server/middleware.js from /var/task/apps/web/___next_launcher.cjs not supported.
middleware.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead either rename middleware.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /var/task/apps/web/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

    at /opt/rust/nodejs.js:2:13527
    at Function.Jr (/opt/rust/nodejs.js:2:13905)
    at Ue.e.<computed>.Be._load (/opt/rust/nodejs.js:2:13497)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14) {
  code: 'ERR_REQUIRE_ESM'
}
Node.js process exited with exit status: 1. The logs above can help with debugging the issue.

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:41 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T6000
  Available memory (MB): 16384
  Available CPU cores: 8
Binaries:
  Node: 24.10.0
  npm: 11.6.0
  Yarn: N/A
  pnpm: 10.13.1
Relevant Packages:
  next: 16.0.3 // Latest available version is detected (16.0.3).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/mburumaxwell/dependabot-azure-devops/tree/main/apps/web

To Reproduce

  1. Create next 16 app
  2. Set `"type": "module"
  3. Add proxy.ts with some basic logic
  4. Deploy to vercel
  5. Make a request that

Current vs. Expected behavior

ESM-only should be supported on proxy/middleware too. Instead, I get the error this error from the application logs:

Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/apps/web/.next/server/middleware.js from /var/task/apps/web/___next_launcher.cjs not supported.
middleware.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead either rename middleware.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /var/task/apps/web/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

    at /opt/rust/nodejs.js:2:13527
    at Function.Jr (/opt/rust/nodejs.js:2:13905)
    at Ue.e.<computed>.Be._load (/opt/rust/nodejs.js:2:13497)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14) {
  code: 'ERR_REQUIRE_ESM'
}
Node.js process exited with exit status: 1. The logs above can help with debugging the issue.
Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/apps/web/.next/server/middleware.js from /var/task/apps/web/___next_launcher.cjs not supported.
middleware.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead either rename middleware.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /var/task/apps/web/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

    at /opt/rust/nodejs.js:2:13527
    at Function.Jr (/opt/rust/nodejs.js:2:13905)
    at Ue.e.<computed>.Be._load (/opt/rust/nodejs.js:2:13497)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14) {
  code: 'ERR_REQUIRE_ESM'
}
Node.js process exited with exit status: 1. The logs above can help with debugging the issue.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:32:41 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T6000
  Available memory (MB): 16384
  Available CPU cores: 8
Binaries:
  Node: 24.10.0
  npm: 11.6.0
  Yarn: N/A
  pnpm: 10.13.1
Relevant Packages:
  next: 16.0.3 // Latest available version is detected (16.0.3).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:
  output: N/A

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

Turbopack, Middleware

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

Vercel (Deployed)

Additional context

No response

extent analysis

TL;DR

The issue can be resolved by renaming the middleware.js file to end in .cjs or by changing the requiring code to use dynamic import.

Guidance

  • The error message indicates that the middleware.js file is being treated as an ES module, but it's being required by a CommonJS module. To fix this, you can either rename the middleware.js file to middleware.cjs or change the requiring code to use dynamic import.
  • Verify that the middleware.js file is not being used as an ES module in any other part of the codebase.
  • Check the package.json file to ensure that the "type" field is set to "module" and that all .js files in the package scope are intended to be ES modules.
  • Consider changing the "type" field to "commonjs" in the package.json file if you intend to use CommonJS modules throughout the project.

Example

// Instead of using require
// const middleware = require('./middleware');

// Use dynamic import
const middleware = await import('./middleware.js');

Notes

The solution assumes that the middleware.js file is not being used as an ES module in any other part of the codebase. If it is, you may need to refactor the code to use dynamic import or rename the file to end in .cjs.

Recommendation

Apply the workaround by renaming the middleware.js file to middleware.cjs or changing the requiring code to use dynamic import, as this is a more targeted solution that does not require changing the entire project's module type.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING