vitest-dev/vitest · error · TypeError
SchemaMatching expected to receive a Standard Schema.
Error message
SchemaMatching expected to receive a Standard Schema.
What it means
SchemaMatching (expect.schemaMatching) requires a Standard Schema object — one exposing the '~standard' descriptor with a validate function. isStandardSchema(sample) returns false for plain objects, classes, or zod/valibot versions that predate Standard Schema support.
Solutions
- Use a schema library that implements Standard Schema (zod v4+, valibot, arktype) and pass the schema object directly.
- Upgrade the schema library to a version that ships Standard Schema support.
- If stuck on zod v3/Yup/Joi, write a custom matcher or upgrade rather than passing the raw schema.
Example fix
// before (zod v3 — not a Standard Schema)
import { z } from 'zod' // v3
expect(payload).toEqual(expect.schemaMatching(z.object({ id: z.number() })))
// after (zod v4 — Standard Schema compliant)
import { z } from 'zod' // v4
expect(payload).toEqual(expect.schemaMatching(z.object({ id: z.number() }))) Defensive patterns
Strategy: type-guard
Validate before calling
function isStandardSchema(v): boolean {
return v != null && typeof v === 'object' && '~standard' in v && typeof v['~standard']?.validate === 'function'
}
function asSchemaMatching(schema) {
if (!isStandardSchema(schema)) {
throw new TypeError('Pass a Standard Schema (zod v4 / valibot / arktype)')
}
return expect.schemaMatching(schema)
} Type guard
function isStandardSchema(v): v is { '~standard': { validate: (v: unknown) => unknown } } {
return v != null && typeof v === 'object' && '~standard' in v && typeof (v as any)['~standard']?.validate === 'function'
} Prevention
- Use a Standard Schema-compliant library (zod v4+, valibot, arktype).
- Upgrade legacy zod v3/Yup/Joi setups rather than passing raw schemas.
- Verify the '~standard' descriptor exists before passing the schema.
When it happens
Trigger: expect.schemaMatching(sample) where sample lacks the '~standard' key (e.g. a raw z.object call on zod v3, a plain validation function, or a class instance).
Common situations: Using zod v3 (no Standard Schema) — Standard Schema landed in zod v4 / valibot v0.31+ / arktype; passing a Yup or Joi schema (no Standard Schema adapter); wrapping the schema in an extra layer.
Related errors
- Async schema validation is not supported in asymmetric…
- any() expects to be passed a constructor function. Please…
- Asymmetric matcher does not implement toAsymmetricMatcher()
- 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/0788df423369605e.
Report an issue: GitHub.
Appendix: source
Thrown at packages/expect/src/jest-asymmetric-matchers.ts:404
override getExpectedType() {
return 'number'
}
override toAsymmetricMatcher(): string {
return [
this.toString(),
this.sample,
`(${pluralize('digit', this.precision)})`,
].join(' ')
}
}
export class SchemaMatching extends AsymmetricMatcher<StandardSchemaV1<unknown, unknown>> {
private result: StandardSchemaV1.Result<unknown> | undefined
constructor(sample: StandardSchemaV1<unknown, unknown>, inverse = false) {
if (!isStandardSchema(sample)) {
throw new TypeError(
'SchemaMatching expected to receive a Standard Schema.',
)
}
super(sample, inverse)
}
asymmetricMatch(other: unknown): boolean {
const result = this.sample['~standard'].validate(other)
// Check if the result is a Promise (async validation)
if (result instanceof Promise) {
throw new TypeError('Async schema validation is not supported in asymmetric matchers.')
}
this.result = result
const pass = !this.result.issues || this.result.issues.length === 0
return this.inverse ? !pass : passView on GitHub (pinned to 1fa9837ec2)