vitest-dev/vitest · error · TypeError
Asymmetric matcher does not implement toAsymmetricMatcher()
Error message
Asymmetric matcher ${val.constructor.name} does not implement toAsymmetricMatcher() What it means
The AsymmetricMatcher pretty-format plugin serializes objects carrying the asymmetric matcher $$typeof symbol. After handling built-in matchers (StringMatching, StringContaining and their negations), if the matcher object has no toAsymmetricMatcher() method the plugin cannot render it and throws. This protects against custom matcher objects that declare the asymmetric typeof but skip the serialization contract.
Example fix
// before
class FooMatcher { $$typeof = asymmetricMatcher; sample = 'x' }
// after
class FooMatcher { $$typeof = asymmetricMatcher; sample = 'x'; toAsymmetricMatcher() { return `Foo<${this.sample}>` } } Defensive patterns
Strategy: type-guard
Type guard
function isSerializableMatcher(v: any): boolean {
return v && v.$$typeof === Symbol.for('jest.asymmetricMatcher') && typeof v.toAsymmetricMatcher === 'function'
} Prevention
- Implement toAsymmetricMatcher() on every custom matcher class
- Extend a built-in matcher base that already serializes
- Unit-test custom matchers through pretty-format to catch missing serialization
When it happens
Trigger: Defining a custom asymmetric matcher (object with $$typeof equal to the asymmetricMatcher symbol) without implementing toAsymmetricMatcher(); passing such a matcher to expect/pretty-format output.
Common situations: Extending expect with a custom matcher class that sets $$typeof but forgets the serialize method; using a matcher from a library that does not implement the full asymmetric matcher interface; version mismatch in the asymmetric matcher symbol.
Related errors
- any() expects to be passed a constructor function. Please…
- Async schema validation is not supported in asymmetric…
- error.message
- Expected is not a Number
- Expected is not a string
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/b57192d1b271104e.
Report an issue: GitHub.
Appendix: source
Thrown at packages/pretty-format/src/plugins/AsymmetricMatcher.ts:84
stringedValue
+ SPACE
+ printer(val.sample, config, indentation, depth, refs)
)
}
if (
stringedValue === 'StringContaining'
|| stringedValue === 'StringNotContaining'
) {
return (
stringedValue
+ SPACE
+ printer(val.sample, config, indentation, depth, refs)
)
}
if (typeof val.toAsymmetricMatcher !== 'function') {
throw new TypeError(
`Asymmetric matcher ${val.constructor.name} does not implement toAsymmetricMatcher()`,
)
}
return val.toAsymmetricMatcher()
}
const test: NewPlugin['test'] = (val: any) =>
val && val.$$typeof === asymmetricMatcher
const plugin: NewPlugin = { serialize, test }
export default plugin
View on GitHub (pinned to 1fa9837ec2)