You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Jest Test Failures After @noble/ciphers v2.0.0 Update #4531
Current behavior: Jest tests fail with the following error when importing Better Auth:
Cannot use import statement outside a module
at /node_modules/@noble/ciphers/chacha.js:17
import { createCipher, createPRG, rotl } from "./_arx.js";
^^^^^^
Expected behavior: Jest tests should run successfully when importing Better Auth, as they did before September 5, 2025.
Which area(s) are affected? (Select all that apply)
Package
Auth config (if applicable)
Additional context
The recent update to @noble/ciphers@2.0.0 (commit 9833a7e - "chore: update jose and crypto dependencies") introduced a breaking change:
Previous: @noble/ciphers@0.6.0 supported both CommonJS and ESM
Current: @noble/ciphers@2.0.0 is ESM-only and dropped CommonJS support entirely
The Problem: Better Auth's CommonJS build (dist/crypto/index.cjs) tries to require('@noble/ciphers/chacha.js'), but Jest cannot require ESM-only modules in CommonJS environments.
Dependencies that changed:
Also this is the first time I have ever submitted an issue on an open source project, so let me know if this is wrong or I did something unclear. For context my tests worked last week, and I root caused this change with Claude Code bc a recent commit to an unrelated branch (not even touching better-auth) started failing in CI pipeline.
@dosu Hey! I dug into this a bit more and found the specific issue. Better Auth's CommonJS build in dist/crypto/index.cjs is trying to require('@noble/ciphers/chacha.js'), I believe the problem is that @noble/ciphers@2.0.0 went pure ESM and completely dropped CommonJS support?
Workaround that worked for me: I managed to get my tests working again by switching Jest to ESM mode with this config:
Hi @koudesh3! I'm Dosu and I’m helping the better-auth team.
You're exactly right—@noble/ciphers@2.0.0 is now ESM-only, and this breaks Better Auth's CommonJS build when used in environments like Jest that default to CommonJS. The error happens because the CommonJS build tries to require ESM-only modules, which Node and Jest can't handle without special configuration.
Your Jest config workaround (using ESM mode and transforming node_modules for better-auth and @noble) is currently the best way to resolve this for test environments. This approach is necessary because Better Auth's codebase imports @noble/ciphers using ESM syntax and doesn't provide a fallback for CommonJS consumers. The dependency update that introduced this breaking change is documented in PR #4433, which also notes the new Node.js version requirements.
For others running into this: either use a Jest ESM preset as shown above, or ensure your Node.js version is 20.19.0+ (or 22.12.0+/23.0.0+) to get better ESM interop, but Jest will still need ESM config tweaks. There isn't an official alternative workaround or codebase fix at this time—your solution is the recommended path for now.
after upgrading from "better-auth": "^1.2.10" to "better-auth": "^1.3.9", it works in localhost, but not when i deploy in render.com
Here you have the full error:
==> Uploading build...
==> Uploaded in 5.1s. Compression took 5.2s
==> Build successful 🎉
==> Deploying...
==> Running 'npm run start:server'
> start:server
> npm run start -w server
> start
> node dist/index.js
/opt/render/project/src/node_modules/better-auth/dist/crypto/index.cjs:315
undefined
^
Error [ERR_REQUIRE_ESM]: require() of ES Module /opt/render/project/src/node_modules/@noble/ciphers/chacha.js from /opt/render/project/src/node_modules/better-auth/dist/crypto/index.cjs not supported.
Instead change the require of chacha.js in /opt/render/project/src/node_modules/better-auth/dist/crypto/index.cjs to a dynamic import() which is available in all CommonJS modules.
at TracingChannel.traceSync (node:diagnostics_channel:315:14)
at Object.<anonymous> (/opt/render/project/src/node_modules/better-auth/dist/crypto/index.cjs:4:19) {
code: 'ERR_REQUIRE_ESM'
}
Node.js v22.11.0
npm error Lifecycle script `start` failed with error:
npm error code 1
npm error path /opt/render/project/src/server
npm error workspace @fsb/server
npm error location /opt/render/project/src/server
npm error command failed
npm error command sh -c node dist/index.js
==> Exited with status 1
==> Common ways to troubleshoot your deploy: https://render.com/docs/troubleshooting-deploys
==> Running 'npm run start:server'
> start:server
> npm run start -w server
> start
> node dist/index.js
/opt/render/project/src/node_modules/better-auth/dist/crypto/index.cjs:315
undefined
^
Error [ERR_REQUIRE_ESM]: require() of ES Module /opt/render/project/src/node_modules/@noble/ciphers/chacha.js from /opt/render/project/src/node_modules/better-auth/dist/crypto/index.cjs not supported.
Instead change the require of chacha.js in /opt/render/project/src/node_modules/better-auth/dist/crypto/index.cjs to a dynamic import() which is available in all CommonJS modules.
at TracingChannel.traceSync (node:diagnostics_channel:315:14)
at Object.<anonymous> (/opt/render/project/src/node_modules/better-auth/dist/crypto/index.cjs:4:19) {
code: 'ERR_REQUIRE_ESM'
}
Node.js v22.11.0
npm error Lifecycle script `start` failed with error:
npm error code 1
npm error path /opt/render/project/src/server
npm error workspace @fsb/server
npm error location /opt/render/project/src/server
npm error command failed
npm error command sh -c node dist/index.js
Thanks for @koudesh3's solution, it worked out fine for me.
For anyone who has the same problem with jest version 29 or later, jest may output (WARN) Define `ts-jest` config under `globals` is deprecated. Please do transform: { <transform_regex>: ['ts-jest', { /* ts-jest config goes here in Jest */ }], },, just do as it suggested and replace the global part with this: transform {'^.+\\.(t|j)s$':['ts-jest', {useESM: true}]}.
As an alternative solution, instead of configuring jest and ts-jest to use ESM mode, try the config here: jestjs/jest#15275 (comment). It basically ask ts-jest to transform all pure ESM packages to CJS:).
I am having the same issue in a nestjs project, but with an other package:
node_modules/.pnpm/better-auth@1.4.16_@prisma+client@7.2.0_prisma@7.2.0_@types+react@19.2.9_react-dom@19.2_81191c1fa7c8d926ad08a18f97a7ee66/node_modules/better-auth/dist/integrations/node.mjs:1
({"Object.":function(module,exports,require,__dirname,__filename,jest){import { toNodeHandler as toNodeHandler$1 } from "better-call/node";
I tried using @OscarCornish fix, but that doesn't work
@Drischdaan Not sure what has changed in recent versions that might break my fix, but I ended up moving our project to use Vitest, which worked with no issues. If you have the capacity, I'd recommend it.
Otherwise, I think I setup a test file with just the better-auth import, then I was checking the jest output to see which modules weren't getting transformed properly, and adding them to the regex
Activity
koudesh3 commentedon Sep 8, 2025
Also this is the first time I have ever submitted an issue on an open source project, so let me know if this is wrong or I did something unclear. For context my tests worked last week, and I root caused this change with Claude Code bc a recent commit to an unrelated branch (not even touching better-auth) started failing in CI pipeline.
koudesh3 commentedon Sep 8, 2025
@dosu Hey! I dug into this a bit more and found the specific issue. Better Auth's CommonJS build in
dist/crypto/index.cjsis trying torequire('@noble/ciphers/chacha.js'), I believe the problem is that @noble/ciphers@2.0.0 went pure ESM and completely dropped CommonJS support?Workaround that worked for me: I managed to get my tests working again by switching Jest to ESM mode with this config:
This tells Jest to handle Better Auth and the @noble packages as ES modules instead of trying to require() them in CommonJS
mode.
dosubot commentedon Sep 8, 2025
Hi @koudesh3! I'm Dosu and I’m helping the better-auth team.
You're exactly right—@noble/ciphers@2.0.0 is now ESM-only, and this breaks Better Auth's CommonJS build when used in environments like Jest that default to CommonJS. The error happens because the CommonJS build tries to require ESM-only modules, which Node and Jest can't handle without special configuration.
Your Jest config workaround (using ESM mode and transforming node_modules for better-auth and @noble) is currently the best way to resolve this for test environments. This approach is necessary because Better Auth's codebase imports @noble/ciphers using ESM syntax and doesn't provide a fallback for CommonJS consumers. The dependency update that introduced this breaking change is documented in PR #4433, which also notes the new Node.js version requirements.
For others running into this: either use a Jest ESM preset as shown above, or ensure your Node.js version is 20.19.0+ (or 22.12.0+/23.0.0+) to get better ESM interop, but Jest will still need ESM config tweaks. There isn't an official alternative workaround or codebase fix at this time—your solution is the recommended path for now.
If you need more background, see the related issue about ESM errors in CommonJS projects.
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

himself65 commentedon Sep 11, 2025
Node.js 23.11.0 is not a stable version. I believe that the latest Node.js supports load ESM in the CJS module.
himself65 commentedon Sep 11, 2025
Related: nodejs/node#51977
alan345 commentedon Sep 15, 2025
after upgrading from
"better-auth": "^1.2.10"to"better-auth": "^1.3.9", it works in localhost, but not when i deploy inrender.comHere you have the full error:
himself65 commentedon Sep 15, 2025
22.11.0 doesn't support it by default. You might need
--experimental-require-moduleI thinkkoudesh3 commentedon Sep 15, 2025
Thank you!!
OscarCornish commentedon Sep 30, 2025
For anyone whom comes across this using pnpm, the solution from koudesh3 worked for me, but after tweaking to allow for pnpms node_modules structure:
Wellshh commentedon Nov 6, 2025
Thanks for @koudesh3's solution, it worked out fine for me.
For anyone who has the same problem with jest version 29 or later, jest may output
(WARN) Define `ts-jest` config under `globals` is deprecated. Please do transform: { <transform_regex>: ['ts-jest', { /* ts-jest config goes here in Jest */ }], },, just do as it suggested and replace the global part with this:transform {'^.+\\.(t|j)s$':['ts-jest', {useESM: true}]}.As an alternative solution, instead of configuring jest and ts-jest to use ESM mode, try the config here: jestjs/jest#15275 (comment). It basically ask ts-jest to transform all pure ESM packages to CJS:).
Drischdaan commentedon Jan 21, 2026
I am having the same issue in a nestjs project, but with an other package:
node_modules/.pnpm/better-auth@1.4.16_@prisma+client@7.2.0_prisma@7.2.0_@types+react@19.2.9_react-dom@19.2_81191c1fa7c8d926ad08a18f97a7ee66/node_modules/better-auth/dist/integrations/node.mjs:1
({"Object.":function(module,exports,require,__dirname,__filename,jest){import { toNodeHandler as toNodeHandler$1 } from "better-call/node";
I tried using @OscarCornish fix, but that doesn't work
OscarCornish commentedon Jan 21, 2026
@Drischdaan Not sure what has changed in recent versions that might break my fix, but I ended up moving our project to use Vitest, which worked with no issues. If you have the capacity, I'd recommend it.
Otherwise, I think I setup a test file with just the better-auth import, then I was checking the jest output to see which modules weren't getting transformed properly, and adding them to the regex
Drischdaan commentedon Jan 21, 2026
EDIT:
Switching to vitest fixed the issues. Thanks for the help
Original Comment:
@OscarCornish I created just a file with the import and added all the packages to the list. This is my jest config:
{ "preset": "ts-jest/presets/default-esm", "moduleFileExtensions": ["js", "json", "ts"], "rootDir": ".", "testRegex": ".e2e-spec.ts$", "setupFilesAfterEnv": ["./setup.e2e.ts"], "transform": { "^.+\\.(t|j)s$": ["ts-jest", { "useESM": true }] }, "extensionsToTreatAsEsm": [".ts"], "transformIgnorePatterns": [ "/node_modules/(?!.*(better-auth|@noble|@thallesp)/)" ] }And that's the console output: