vitest-dev/vitest · error · Error
expected must be a function, received
Error message
expected must be a function, received ${typeof expected} What it means
Thrown inside the snapshot helper `getError` when the value handed to `toThrowErrorMatchingSnapshot` / `toThrowErrorMatchingInlineSnapshot` is not a function AND the assertion is not in promise mode (i.e. no `rejects`/`throws` promise flag). In the non-promise path Vitest expects a callable that throws, so a non-function value is a usage error.
Solutions
- Wrap the throwing code in a function: `expect(() => { throw new Error('x') }).toThrowErrorMatchingSnapshot()`.
- If asserting on a rejected promise, use the promise form: `await expect(promise).rejects.toThrowErrorMatchingSnapshot()`.
- Double-check you are not passing an already-caught error object.
Example fix
// before
const err = new Error('boom')
expect(err).toThrowErrorMatchingSnapshot()
// after
expect(() => { throw new Error('boom') }).toThrowErrorMatchingSnapshot() Defensive patterns
Strategy: type-guard
Validate before calling
function snapshotThrow(fn) {
if (typeof fn !== 'function') throw new Error('pass a function that throws')
return expect(fn).toThrowErrorMatchingSnapshot()
} Type guard
function isThrowingFn(v): v is () => void {
return typeof v === 'function'
} Prevention
- Always wrap throwing code in an arrow function for toThrowErrorMatching* assertions.
- For rejected promises, use expect(p).rejects.toThrowErrorMatchingSnapshot().
- Never pass an already-caught Error object to these assertions.
When it happens
Trigger: Writing `expect(myError).toThrowErrorMatchingSnapshot()` (passing an Error instance directly) instead of `expect(() => { throw myError }).toThrowErrorMatchingSnapshot()`; passing a string or object literal to the assertion; using the assertion on a non-throwing expression.
Common situations: Confusing `expect(...).toThrow()` style (which wraps a function) with passing the error itself; refactor that moved the throw out of an arrow function; copy-pasting from `toThrow` examples without the function wrapper.
Related errors
- cannot be used with "not
- ' ' cannot be used without test context
- snapshot function didn't throw
- A function to advance timers was called but the timers APIs…
- aria adapter expects an Element
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/b7f699f68ed08614.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vitest/src/integrations/snapshot/chai.ts:30
import { getNames } from '../../utils/tasks'
let _client: SnapshotClient
export function getSnapshotClient(): SnapshotClient {
if (!_client) {
_client = new SnapshotClient({
isEqual: (received, expected) => {
return equals(received, expected, [iterableEquality, subsetEquality])
},
})
}
return _client
}
function getError(expected: () => void | Error, promise: string | undefined) {
if (typeof expected !== 'function') {
if (!promise) {
throw new Error(
`expected must be a function, received ${typeof expected}`,
)
}
// when "promised", it receives thrown error
return expected
}
try {
expected()
}
catch (e) {
return e
}
throw new Error('snapshot function didn\'t throw')
}
View on GitHub (pinned to 1fa9837ec2)