vitest-dev/vitest · error · TypeError
[vitest] Mocks require an id string.
Error message
[vitest] Mocks require an id string.
What it means
Thrown as a `TypeError` by `MockerRegistry.register` (multi-argument overload) when the `id` argument is not a string. The `id` is the resolved module id used as a secondary registry key (via `registryById`) and for invalidation; it must be a string so the mock can be tracked and cleared across test isolation boundaries.
Solutions
- Ensure the RPC resolution returns a string `resolvedId` and that it is forwarded as the `id` argument.
- Confirm the argument order matches `(type, raw, id, url, factoryOrRedirect)`.
- If the id is genuinely absent, fall back to the resolved file path before calling `register`.
Example fix
// before — id missing from the RPC result
const { resolvedUrl } = await rpc.resolveMock(...)
registry.register('automock', raw, undefined, resolvedUrl)
// after — forward resolvedId
const { resolvedId, resolvedUrl } = await rpc.resolveMock(...)
registry.register('automock', raw, resolvedId, resolvedUrl) Defensive patterns
Strategy: validation
Validate before calling
// Validate id is a string before calling register.
function registerSafe(registry: MockerRegistry, type: any, raw: string, id: unknown, url: string, extra?: any) {
if (typeof id !== 'string') {
throw new TypeError('id must be a string')
}
return registry.register(type, raw, id, url, extra)
} Type guard
function isIdString(value: unknown): value is string {
return typeof value === 'string'
} Prevention
- Ensure RPC resolveMock returns a string resolvedId and forward it as id.
- Respect the (type, raw, id, url) argument order.
- Add unit tests covering the full argument-shape matrix for register().
When it happens
Trigger: Calling `register(type, raw, id, url, ...)` with `id` set to `undefined` or a non-string — typically because the RPC resolution did not return a `resolvedId`, or the caller passed arguments out of order.
Common situations: An RPC `resolveMock`/`resolveId` response missing `resolvedId`; a forked runner that drops the id field; argument-order confusion against the `(type, raw, id, url)` signature.
Related errors
- [vitest] Mocks require a raw string.
- [vitest] Mocks require a url string.
- [vitest] Cannot register a mock that is already defined…
- Cannot set serialized manual mock. Define a factory…
- invalid snapshot serializer in
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/6f53ba28ed017703.
Report an issue: GitHub.
Appendix: source
Thrown at packages/mocker/src/registry.ts:103
}
else if (event.type === 'manual') {
throw new Error(`Cannot set serialized manual mock. Define a factory function manually with \`ManualMockedModule.fromJSON()\`.`)
}
else {
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') {View on GitHub (pinned to 1fa9837ec2)