vitest-dev/vitest · error · TypeError

Async schema validation is not supported in asymmetric…

Error message

Async schema validation is not supported in asymmetric matchers.

What it means

SchemaMatching's asymmetricMatch calls sample['~standard'].validate(other) and throws a TypeError if the result is a Promise. Asymmetric matchers are synchronous, so async schema validation (refinements, transforms that await) cannot be evaluated inline.

Solutions

  1. Remove async refinements/transforms from the schema used in schemaMatching, or use a separate sync schema for the assertion.
  2. Validate explicitly with await schema['~standard'].validate(value) inside an async test and assert on the issues array.
  3. Use expect(await result).toEqual(...) patterns with a pre-validated value instead of the asymmetric matcher.

Example fix

// before: schema has an async refinement
const schema = z.object({ email: z.string().email().refine(async (v) => await isUnique(v)) })
expect(payload).toEqual(expect.schemaMatching(schema))
// after: validate explicitly in an async test
const result = await schema['~standard'].validate(payload)
expect(result.issues ?? []).toEqual([])
Defensive patterns

Strategy: validation

Validate before calling

// Detect async validation up front and switch strategies.
async function validateSyncOrThrow(schema, value) {
  const result = schema['~standard'].validate(value)
  if (result instanceof Promise) {
    throw new TypeError('Schema uses async validation; await it in the test instead.')
  }
  return result
}

Type guard

function isSyncSchemaResult(result): boolean {
  return !(result instanceof Promise)
}

Try / catch

try {
  expect(payload).toEqual(expect.schemaMatching(schema))
} catch (e) {
  if (/Async schema validation is not supported/.test(String(e?.message))) {
    const r = await schema['~standard'].validate(payload)
    expect(r.issues ?? []).toEqual([])
    return
  }
  throw e
}

Prevention

When it happens

Trigger: Using expect.schemaMatching(schema) in a synchronous expect(...).toEqual(...) where the schema contains async refinements or async transforms, so validate() returns a Promise.

Common situations: Zod schemas with .refine(async ...), valibot schemas with async actions, or any schema whose validation pipeline is async; using schemaMatching inside toEqual instead of an async-aware assertion.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/dc2501d4c85193fa. Report an issue: GitHub.

Appendix: source

Thrown at packages/expect/src/jest-asymmetric-matchers.ts:416

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 : pass
  }

  toString() {
    return `Schema${this.inverse ? 'Not' : ''}Matching`
  }

  getExpectedType() {
    return 'object'
  }

  toAsymmetricMatcher(): string {
    const { utils } = this.getMatcherContext()

View on GitHub (pinned to 1fa9837ec2)