vitest-dev/vitest · error · TypeError

${matcherHint('.toBeFasterThan')} expects the expected value

Error message

${matcherHint('.toBeFasterThan')} expects the expected value to be a benchmark result.

What it means

Companion to error 177, thrown by toBeFasterThan when the EXPECTED (second) argument is not a BenchResult. The matcher needs both operands to expose latency.mean and throughput.mean so it can compute the delta threshold and the ops/sec display. Passing a number/string/object-without-stats as the baseline triggers this guard right after the actual check.

Source

Thrown at packages/vitest/src/integrations/chai/bench.ts:28

  )
}

function formatOps(ops: number): string {
  return ops.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
}

export const benchMatchers: MatchersObject = {
  toBeFasterThan(actual: unknown, expected: unknown, options?: { delta?: number }) {
    const { matcherHint, RECEIVED_COLOR, EXPECTED_COLOR } = this.utils
    const delta = options?.delta ?? 0

    if (!isBenchResult(actual)) {
      throw new TypeError(
        `${matcherHint('.toBeFasterThan')} expects the actual value to be a benchmark result.`,
      )
    }
    if (!isBenchResult(expected)) {
      throw new TypeError(
        `${matcherHint('.toBeFasterThan')} expects the expected value to be a benchmark result.`,
      )
    }

    const threshold = expected.latency.mean * (1 - delta)
    const pass = actual.latency.mean < threshold

    return {
      pass,
      message: () => {
        const relation = ((actual.latency.mean - expected.latency.mean) / expected.latency.mean * 100).toFixed(2)
        return pass
          ? `${matcherHint('.not.toBeFasterThan')}\n\nExpected to not be faster, but was ${Math.abs(Number(relation))}% faster.\n\n`
          + `Received: ${RECEIVED_COLOR(formatOps(actual.throughput.mean))} ops/sec\n`
          + `Expected: ${EXPECTED_COLOR(formatOps(expected.throughput.mean))} ops/sec\n`
          : `${matcherHint('.toBeFasterThan')}\n\nExpected to be faster${delta > 0 ? ` by at least ${(delta * 100).toFixed(0)}%` : ''}, but was ${Number(relation) > 0 ? `${relation}% slower` : `only ${Math.abs(Number(relation))}% faster`}.\n\n`
            + `Received: ${RECEIVED_COLOR(formatOps(actual.throughput.mean))} ops/sec\n`
            + `Expected: ${EXPECTED_COLOR(formatOps(expected.throughput.mean))} ops/sec\n`

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Pass a real BenchResult as the second argument (one obtained from another bench() task).
  2. Use the options.delta argument ({ delta: 0.1 }) to express a percentage threshold instead of a numeric baseline.
  3. Build the baseline by running bench() against the reference implementation and storing the result.
  4. Switch to toBeLessThan if you want a numeric comparison.

Example fix

// before
expect(result).toBeFasterThan(100)

// after
expect(result).toBeFasterThan(baselineResult, { delta: 0.1 })
Defensive patterns

Strategy: type-guard

Validate before calling

function isBenchResult(value: unknown): value is { latency: { mean: number }; throughput: { mean: number } } {
  return typeof value === 'object' && value !== null
    && 'latency' in value && typeof (value as any).latency?.mean === 'number'
}
if (!isBenchResult(baseline)) {
  throw new TypeError('baseline must be a BenchResult; use { delta } for thresholds')
}

Type guard

function isBenchResult(value: unknown): value is { latency: { mean: number }; throughput: { mean: number } } {
  return typeof value === 'object' && value !== null
    && 'latency' in value && typeof (value as any).latency?.mean === 'number'
}

Prevention

When it happens

Trigger: expect(result).toBeFasterThan(100); passing a numeric threshold instead of a baseline BenchResult; using a plain object as the baseline; passing the result of a non-bench measurement.

Common situations: Assuming toBeFasterThan takes a percentage/millisecond delta instead of a baseline result; mixing up toBeFasterThan with toBeLessThan; refactoring that replaced the baseline bench result with a number.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/4b783175b853f963.json. Report an issue: GitHub.