vitest-dev/vitest · error · AssertionError

${formatReturns(spy, results, msg, value)}

Error message

${formatReturns(spy, results, msg, value)}

What it means

AssertionError thrown by toHaveResolvedWith/toHaveReturnedWith/toReturnWith when the spy never produced a matching return/resolved value (positive) or did produce one under .not. The message is enriched by formatReturns, which diffs each recorded result against the expected value.

Source

Thrown at packages/expect/src/jest-expect.ts:967

    ] satisfies ReturnMatcher<[any]>[]
  ).forEach(({ name, condition, action }) => {
    def(name, function (value: any) {
      const spy = getSpy(this)
      const pass = condition(spy, value)
      const isNot = utils.flag(this, 'negate') as boolean

      if ((pass && isNot) || (!pass && !isNot)) {
        const spyName = spy.getMockName()
        const msg = utils.getMessage(this, [
          pass,
          `expected "${spyName}" to ${action} with: #{exp} at least once`,
          `expected "${spyName}" to not ${action} with: #{exp}`,
          value,
        ])

        const results
          = action === 'return' ? spy.mock.results : spy.mock.settledResults
        throw new AssertionError(formatReturns(spy, results, msg, value))
      }
    })
  });
  (
    [
      {
        name: 'toHaveLastResolvedWith',
        condition: (spy, value) => {
          const result
            = spy.mock.settledResults.at(-1)
          return Boolean(
            result
            && result.type === 'fulfilled'
            && jestEquals(result.value, value),
          )
        },
        action: 'resolve',
      },

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Inspect spy.mock.results / spy.mock.settledResults in a debug step to see what was actually returned.
  2. Use expect.any / expect.objectContaining to relax the expected shape.
  3. Ensure the mock actually executed the path that returns — a thrown call has type 'throw' and will not match a 'return' assertion.

Example fix

// before
expect(api.fetch).toHaveReturnedWith({ id: 1 });
// after
expect(api.fetch).toHaveResolvedWith(expect.objectContaining({ id: 1 }));
Defensive patterns

Strategy: validation

Validate before calling

const returns = spy.mock.results;
if (!returns.some(r => r.type === 'return' && jestEquals(r.value, expected))) {
  console.warn('no matching return; results:', returns);
}

Prevention

When it happens

Trigger: expect(spy).toHaveReturnedWith(value) where no entry in spy.mock.results (type==='return') matches; or expect(spy).toHaveResolvedWith(value) where no settledResults entry (type==='fulfilled') matches. Condition (pass && isNot) || (!pass && !isNot) controls the throw.

Common situations: Asserting on a mock's return value when the mock threw instead of returned, when it resolved with a different shape, or when it was never invoked. Also common when the wrong result list is consulted (returns vs settled for async).

Related errors


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