Express hosting on Vercel

I am trying to host an express js app with better-auth, it used to give me this error -

2025-10-28T04:22:13.659Z [error] Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/node_modules/jose/dist/webapi/index.js from /var/task/node_modules/@better-auth/core/dist/oauth2/index.cjs not supported.
Instead change the require of index.js in /var/task/node_modules/@better-auth/core/dist/oauth2/index.cjs to a dynamic import() which is available in all CommonJS modules.
    at /opt/rust/nodejs.js:2:13528
    at Function.Vr (/opt/rust/nodejs.js:2:13906)
    at Ue.e.<computed>.Be._load (/opt/rust/nodejs.js:2:13498)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14) {
  code: 'ERR_REQUIRE_ESM'
}

I tried to import it dynamically, but is that the best solution we got?

If you’re having trouble deploying an Express app, this guide can help.

You can also ask v0 for suggestions tailored to your own project setup.

Hey @gyanendra-7337!

Thanks for joining us here from X, glad we’ve got more context now :blush:

Looks like this error’s happening because your project is mixing CommonJS and ES modules. The jose package is ESM-only, but @better-auth/core is trying to import it using CommonJS (require()), which causes the issue.

Here’s what you can try…

1. Convert your project to ES modules (recommended)

  • Add "type": "module" to your package.json
  • Replace all require() calls with import
  • Make sure to include .js extensions in your imports

This is the cleanest long-term fix and should solve the compatibility issue entirely.

2. Check your better-auth setup

  • Make sure you’re on the latest version of better-auth
  • Check if they have Vercel deployment notes or examples

3. Set your Node.js runtime on Vercel

If you’re using serverless functions, you can explicitly set the runtime:

{
  "functions": {
    "app.js": {
      "runtime": "nodejs18.x"
    }
  }
}

If you’re on Next.js with the App Router, try using an Edge Function or Server Action, which support ES modules out of the box.

@pawlean Thanks for this, crazy support from you.
Thanks a lot

1 Like

Do you have any idea what tsconfig properties we need to set to add file extensions on build?

Glad I could be of help! What I’m here for :slight_smile:

Try updating your tsconfig.json like this:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "outDir": "dist"
  }
}

Then either:

  • Manually include .js in your imports (e.g. import { x } from './utils.js'), or
  • Run a tool like tsc-esm-fix after tsc to automatically add file extensions.

TypeScript itself won’t rewrite the paths, so tsc-esm-fix is the simplest way to make your ESM output work cleanly on Vercel.