jestjs/jest · error · Error
Resolver located at ${resolver} does not export a function o
Error message
Resolver located at ${resolver} does not export a function or an object with "sync" and "async" props What it means
Thrown inside loadResolver when the resolver module exports a value that is neither a function nor an object exposing a `sync` or `async` property. Jest requires one of these two shapes for a custom resolver and rejects anything else (e.g. a string, number, array, or object without the hooks).
Source
Thrown at packages/jest-resolve/src/resolver.ts:959
const loadedResolver = require(resolver);
if (loadedResolver == null) {
throw new Error(`Resolver located at ${resolver} does not export anything`);
}
if (typeof loadedResolver === 'function') {
return loadedResolver as SyncResolver;
}
if (
typeof loadedResolver === 'object' &&
(loadedResolver.sync != null || loadedResolver.async != null)
) {
return loadedResolver as ResolverObject;
}
throw new Error(
`Resolver located at ${resolver} does not export a function or an object with "sync" and "async" props`,
);
}
View on GitHub (pinned to f49721c78e)
Solutions
- Export a function directly: `module.exports = function(path, options) { ... }`.
- Or export `{ sync, async }` (named exactly those keys) where each is a function.
- Verify with `node -e "const r = require('./my-resolver.js'); console.log(typeof r, typeof r.sync, typeof r.async)"` — at least one must be 'function'.
Example fix
// before
module.exports = { resolve: (path, options) => { /* ... */ } };
// after
module.exports = { sync: (path, options) => { /* ... */ } }; Defensive patterns
Strategy: type-guard
Validate before calling
function assertResolverShape(resolverPath) {
const m = require(resolverPath);
const ok = typeof m === 'function' ||
(typeof m === 'object' && m && (typeof m.sync === 'function' || typeof m.async === 'function'));
if (!ok) throw new Error(`Resolver ${resolverPath} must export a function or {sync, async}`);
return m;
} Type guard
type ResolverExport = ((path: string, options: any) => string) | { sync?: Function; async?: Function };
function isResolverExport(m: unknown): m is ResolverExport {
if (typeof m === 'function') return true;
if (typeof m !== 'object' || m === null) return false;
return typeof (m as any).sync === 'function' || typeof (m as any).async === 'function';
} Prevention
- Name the exported hooks exactly `sync` and `async` — no other keys are recognized.
- For a single-implementation resolver, export the function directly to avoid shape mistakes.
- Document the expected export shape in the resolver file's header comment.
When it happens
Trigger: The `resolver` config value points at a module that exports a plain config object, a string, or an object missing both `sync` and `async` keys. Common when someone mistakes the resolver file for a config file or exports a wrapper object like `{ resolve: fn }`.
Common situations: Copy-pasting a resolver example but naming the export `resolve` instead of `sync`/`async`; exporting a class instance whose prototype methods aren't own enumerable `sync`/`async`; pointing `resolver` at the package root whose `main` is a JSON manifest.
Related errors
- Resolver located at ${resolver} does not export anything
- Configuration in ${packageJson} is not valid. Jest expects t
- Multiple configurations found Implicit config resolution d
- For a percentage based memory limit a percentageReference mu
- Unexpected numerical input
AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03).
Data as JSON: /data/errors/94da80e25a828d50.json.
Report an issue: GitHub.