Fix: Jest SyntaxError Unexpected token export (uuid library)
The fix depends on whether the stale uuid build is yours or a transitive dependency's — here is how to tell, and the exact config for each case.
TL;DR#
Jest resolved uuid to node_modules/uuid/dist/esm-browser/index.js, which is
written as an ES module (export { default as v1 } from './v1.js'), then ran
it through Jest's CommonJS wrapper — which cannot parse export. That file is
what uuid's package.json exports map hands back on the default branch;
Jest's own resolver did not consistently honour that map before version 9 of
uuid, which changed its package layout so a plain CommonJS require()
lands on the right build instead. Map uuid to its CommonJS build with
moduleNameMapper, or upgrade the package to uuid@9 or later. If the error
still appears after upgrading your own uuid, a transitive dependency is
still pulling in uuid@8.
node_modules/uuid/dist/esm-browser/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js';
^^^^^^
SyntaxError: Unexpected token 'export'
at Runtime.createScriptFromCode (../node_modules/jest-runtime/build/index.js:1796:14)
at Object.require (../node_modules/@nestjs/common/decorators/core/injectable.decorator.js:4:16)This is the exact trace from the Stack Overflow question (81 votes, 64,696 views):
a NestJS + ts-jest + Puppeteer project where tests ran fine until uuid — a
transitive dependency of something else in the tree — got resolved to its ESM
build the moment Jest's module graph touched it.
Why it happens#
uuid ships several builds in one package: a CommonJS build under dist/,
and ESM builds under dist/esm-node/ and dist/esm-browser/. Which one a
tool picks is decided by the exports map in uuid's package.json — a
standard Node.js feature for pointing different environments (require,
import, browsers) at different files from the same package name. The
error trace above names dist/esm-browser/index.js specifically: on the
uuid major version this question was filed against, that is what the
exports map's default condition resolves to, so any resolver that reads
the map at all without a more specific CommonJS condition can land there —
which is why the file itself reads like it was meant for a <script> tag,
not a Jest test.
Jest's own module resolver (jest-resolve) handled that exports map
inconsistently for a long time — not reading it on some releases, reading it
and landing on the wrong condition on others. One of the people who hit this
exact error documented the workaround in the uuid repository,
writing the fix as:
// jest.config.js
moduleNameMapper: {
// Force module uuid to resolve with the CJS entry point, because Jest does not support package.json.exports. See https://github.com/uuidjs/uuid/issues/451
"uuid": require.resolve('uuid'),
},Jest tracked the gap as its own issue, "Support package exports in
jest-resolve", now closed.
Jest's maintainer confirmed on the uuid thread that "Jest 28 does support
it" once that resolver work landed. The current Jest configuration
docs
describe the surviving knob, testEnvironmentOptions.customExportConditions,
which controls which condition inside a package's exports map Jest
follows — it does not change whether the map is read at all on a recent Jest.
That distinction matters for anyone still debugging this on an older Jest: a
customExportConditions tweak will not fix a resolver that pre-dates the
exports support entirely, only the two config fixes below will.
So on an old Jest, or on a dependency chain where something still resolves to
an old uuid, the resolver falls back to a file that happens to be an ES
module, and Jest's CommonJS wrapper — which runs every file inside a
function(module, exports, require, __dirname, __filename, jest) { ... }
wrapper — meets a bare export keyword it was never written to parse. That
Unexpected token 'export' is JavaScript's own parser rejecting ESM syntax
inside a CommonJS wrapper, not a Jest-specific error message.
Fix#
1. Force the CommonJS build with moduleNameMapper#
This is the fix from the accepted answer (score 135) and confirmed independently in a separate 43-vote answer on the same question:
// jest.config.js
module.exports = {
moduleNameMapper: {
uuid: require.resolve('uuid'),
},
};require.resolve('uuid') returns the path Node's own CommonJS resolver would
pick for uuid — its main entry, not whatever the exports map would hand
to an ESM-aware resolver. This works regardless of which uuid version is
installed, and regardless of which part of the dependency tree pulled it in,
because it rewrites every require('uuid')/import ... from 'uuid' Jest
sees, including ones inside your dependencies' own node_modules.
A shorter form some projects use is moduleNameMapper: { "^uuid$": "uuid" } —
functionally the same redirect, letting Jest's own module resolution (not the
exports map) decide which file uuid means.
2. Or upgrade uuid to major version 9 or later#
Version 9.0.0 of uuid was published on the npm registry on 2022-09-05,
changing the package's exports map so a plain CommonJS require() resolves
to the right build without Jest needing to read the map correctly at all.
Jest's maintainer closed the loop on the uuid issue thread, writing: "Note
that moduleNameMapper is not needed for Jest 29 and uuid v9." If your
code imports uuid directly, bumping the dependency is generally enough —
no Jest config change required — but later reports on the same GitHub
thread, from April 2023, show
the error can still surface on uuid major version 9 with a Jest 29 release,
independently of any transitive dependency; if it does, apply the
moduleNameMapper fix from step 1 as well:
npm install uuidCheck the installed major version afterwards:
npm ls uuid3. If the error survives both fixes, a transitive dependency is still on the old major#
Upgrading your own package.json entry for uuid does not touch the copy a
different dependency bundles internally. On the same GitHub thread, a user
(mbrookson) noted they still needed the workaround because packages such
as next-auth and some @aws-sdk modules were "still reliant on" the old
major release months after version 9 shipped. If the npm ls uuid output
above shows more than one resolved version, the moduleNameMapper fix from
step 1 is the one that covers every copy at once — it rewrites the module
name itself, not a specific file path, so it catches the uuid a dependency
three levels down requires too.
Verify the fix#
Re-run the previously failing suite. The stack trace that named
esm-browser/index.js should be gone; if uuid is still involved anywhere
in the trace, it will now point at a .js file under dist/ (the CommonJS
build) rather than dist/esm-browser/. If the suite passes but a different
package produces the same Unexpected token 'export' shape, the fix is the
same moduleNameMapper pattern applied to that package's name instead — the
Jest resolver gap was never specific to uuid, only widely hit through it
because so many other packages depend on it transitively.
If npm ls uuid printed more than one version earlier, run it again after
the fix: it will still list every resolved copy in the tree (upgrading or
mapping uuid does not collapse duplicate installs into one), but the test
run itself no longer cares, because moduleNameMapper redirects every one
of those copies to the same CommonJS file regardless of which package.json
asked for it. A leftover old uuid under a dependency's own node_modules
is then a disk-size or npm audit concern, not a test-breaking one.
One email a month — the latest explained errors
What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.
A related but different cause: jest itself undefined under native ESM#
If switching your own package.json to "type": "module" is what triggered
test failures, the symptom is usually a different error —
ReferenceError: jest is not defined rather than this SyntaxError — because
Jest stops auto-injecting its globals under native ESM. That is covered
separately in Fix: ReferenceError: jest is not defined (ESM tests). A Vite app that reads import.meta.env hits another member of the same family under Jest, SyntaxError: Cannot use 'import.meta' outside a module, because the transformer compiles the source to CommonJS; the Jest and Vite import.meta fix moves those reads into one module that Jest maps to a stand-in, or runs the tests with Vitest.
Projects doing a gradual CommonJS-to-ESM interop change also run into
ERR_IMPORT_ASSERTION_TYPE_MISSING when importing JSON modules
on current Node.js releases, and a CJS/ESM default-export mismatch on the
TypeScript side shows up as
TS2305: Module Has No Exported Member —
a different parser (tsc, not Jest) rejecting the same kind of interop gap
for a different reason.
These three errors share one root cause family — a package or a test runner disagreeing about whether a module is CommonJS or ESM — but each needs its own fix, because the tool that rejects the file (Jest's runtime wrapper, Node's loader, or the TypeScript compiler) is different in each case.
Frequently Asked Questions
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
Continue Reading
Unexpected any. Specify a different type: fix or disable
Make @typescript-eslint/no-explicit-any go quiet for the right reason: a scoped disable that ESLint actually reads, a config override, or a real type.
Fix: ReferenceError: jest is not defined (ESM tests)
Access Jest's mocking object in native ESM tests without confusing it with the test, expect and global names that remain available by default.
Fix 'originalKeywordKind' DeprecationError in TypeScript
The 'originalKeywordKind' DeprecationError fires when @typescript-eslint packages are stuck on v5 while TypeScript moved on. Upgrade to v6.x and restart ESLint to clear it.


