jestjs/jest · error · Error
Jest: Failed to load ESM at ${filePath} - did you use a defa
Error message
Jest: Failed to load ESM at ${filePath} - did you use a default export? What it means
Thrown by `importModule` (requireOrImportModule.ts:28-32) when an ESM module (`.mjs`/`.mts`, or a `.js` that triggered `ERR_REQUIRE_ESM`) is dynamically imported, `applyInteropRequireDefault` is true, but the resulting namespace has no `default` export. Jest's interop layer expects a default export to hand back to callers that requested the CJS-style default.
Source
Thrown at packages/jest-util/src/requireOrImportModule.ts:29
async function importModule(
filePath: string,
applyInteropRequireDefault: boolean,
) {
try {
const moduleUrl = pathToFileURL(filePath);
// node `import()` supports URL, but TypeScript doesn't know that
const importedModule = await import(
/* webpackIgnore: true */ moduleUrl.href
);
if (!applyInteropRequireDefault) {
return importedModule;
}
if (!importedModule.default) {
throw new Error(
`Jest: Failed to load ESM at ${filePath} - did you use a default export?`,
);
}
return importedModule.default;
} catch (error: any) {
if (error.message === 'Not supported') {
throw new Error(
`Jest: Your version of Node does not support dynamic import - please enable it or use a .cjs file extension for file ${filePath}`,
);
}
throw error;
}
}
export default async function requireOrImportModule<T>(
filePath: string,
applyInteropRequireDefault = true,View on GitHub (pinned to f49721c78e)
Solutions
- Add `export default` to the ESM module: `export default { ... }` instead of `export const ...`.
- If loading through an API that passes `applyInteropRequireDefault=false`, named exports are returned as the namespace - use that variant when you control the call site.
- For Jest config specifically, use the documented ESM form `export default async () => ({...})`.
Example fix
// before: jest.config.mjs
export const config = { testEnvironment: 'node' };
// after
export default { testEnvironment: 'node' }; Defensive patterns
Strategy: type-guard
Validate before calling
// Check the module namespace before relying on .default
const mod = await import(pathToFileURL(filePath).href);
if (!('default' in mod)) throw new Error(`${filePath} needs a default export`); Type guard
const hasDefaultExport = (m: any): boolean => m != null && 'default' in m && m.default !== undefined;
Prevention
- Write ESM Jest config as `export default {...}`.
- For resolvers/transformers written as ESM, default-export the implementation.
- If only named exports make sense, load via the `applyInteropRequireDefault=false` variant.
When it happens
Trigger: Loading a module via `requireOrImportModule(path)` (used for config files, snapshot resolvers, transformers, custom runners) where the target module is ESM with only named exports and no `default`.
Common situations: An ESM config file (`jest.config.mjs`) that does `export const config = {...}` instead of `export default {...}`; a custom snapshot resolver / transformer written as ESM named exports; switching a CJS config (which had `module.exports =`) to ESM and forgetting to switch to `export default`.
Related errors
- Jest: requireOrImportModule path must be absolute, was "${fi
- Invalid first argument, ${descriptor}. It must be a named cl
- Jest: Your version of Node does not support dynamic import -
- jest.config.mts requires native TypeScript support. Ensure y
- Unable to load resolver at ${options.resolver}
AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03).
Data as JSON: /data/errors/da51638b9d9b8380.json.
Report an issue: GitHub.