vitest-dev/vitest · error · TypeError
[vitest] Manual mocks require a factory function.
Error message
[vitest] Manual mocks require a factory function.
What it means
Manual mocks are resolved lazily by invoking a factory function that returns the module's exports. Registering a `'manual'` mock therefore requires the 5th argument to be a callable factory; anything else (omitted, a string, an object) is invalid because the mock could never produce exports.
Source
Thrown at packages/mocker/src/registry.ts:108
throw new Error(`Unknown mock type: ${(event as any).type}`)
}
}
if (typeof raw !== 'string') {
throw new TypeError('[vitest] Mocks require a raw string.')
}
if (typeof url !== 'string') {
throw new TypeError('[vitest] Mocks require a url string.')
}
if (typeof id !== 'string') {
throw new TypeError('[vitest] Mocks require an id string.')
}
if (type === 'manual') {
if (typeof factoryOrRedirect !== 'function') {
throw new TypeError('[vitest] Manual mocks require a factory function.')
}
const mock = new ManualMockedModule(raw, id, url, factoryOrRedirect)
this.add(mock)
return mock
}
else if (type === 'automock' || type === 'autospy') {
const mock = type === 'automock'
? new AutomockedModule(raw, id, url)
: new AutospiedModule(raw, id, url)
this.add(mock)
return mock
}
else if (type === 'redirect') {
if (typeof factoryOrRedirect !== 'string') {
throw new TypeError('[vitest] Redirect mocks require a redirect string.')
}
const mock = new RedirectedModule(raw, id, url, factoryOrRedirect)
this.add(mock)View on GitHub (pinned to d568f8ce37)
Solutions
- Provide a factory returning the module namespace: `registry.register('manual', raw, id, url, () => ({ default: stub }))`.
- If you already have the exports object, wrap it in a thunk: `() => exportsObject`.
- Double-check the overload — the 5th arg's type depends on `type` (function for manual, string for redirect).
Example fix
// before
registry.register('manual', raw, id, url)
// after
registry.register('manual', raw, id, url, () => ({
default: vi.fn(),
helper: vi.fn(),
})) Defensive patterns
Strategy: type-guard
Validate before calling
function registerManual(registry: any, raw: string, id: string, url: string, factory: unknown) {
if (typeof factory !== 'function') {
throw new TypeError('Manual mocks require a factory function () => module namespace.')
}
registry.register('manual', raw, id, url, factory as () => any)
} Type guard
function isFactory(v: unknown): v is () => unknown {
return typeof v === 'function'
} Prevention
- Always type the 5th arg of a manual register call as `() => unknown`.
- If you already have the exports object, wrap as `() => exportsObject`.
- Keep a unit test that registers one manual mock to catch missing-factory regressions.
When it happens
Trigger: Calling `registry.register('manual', raw, id, url)` (factory omitted) or `registry.register('manual', raw, id, url, 'notAFunction')`.
Common situations: Forgetting the factory; copy-pasting a redirect call into a manual call; passing an already-built object instead of a thunk.
Related errors
- Cannot set serialized manual mock. Define a factory function
- Unknown mock type: ${(event as any).type}
- [vitest] Mocks require a raw string.
- [vitest] Mocks require a url string.
- [vitest] Mocks require an id string.
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/13d5ade8b903fc4e.json.
Report an issue: GitHub.