{"id":"0a2db21e1b5df8a8","repo":"vitest-dev/vitest","slug":"vi-when-no-behavior-defined-when-called-with-a","errorCode":null,"errorMessage":"vi.when: no behavior defined when called with [${args.map(arg => stringify(arg)).join(', ')}]","messagePattern":"vi\\.when: no behavior defined when called with \\[(.+?)\\]","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/integrations/mock/when.ts","lineNumber":330,"sourceCode":"      if (equals(args, behavior.arguments, testers)) {\n        return behavior.actions.findLast(action => !(action.remaining === 0 && action.called)) ?? null\n      }\n    }\n\n    return null\n  }\n\n  spy.mockImplementation(\n    // @ts-expect-error cannot resolve generic args\n    (...args: ScopedParameters) => {\n      const action = findAction(args)\n\n      if (action === null) {\n        const onUnmatched = typeof options?.onUnmatched === 'function'\n          ? options.onUnmatched\n          : options?.onUnmatched === 'throw'\n            ? () => {\n                throw new Error(`vi.when: no behavior defined when called with [${args.map(arg => stringify(arg)).join(', ')}]`)\n              }\n            : originalImplementation\n        return onUnmatched?.(...args)\n      }\n\n      action.remaining -= 1\n      action.called = true\n\n      switch (action.type) {\n        case 'return': {\n          return action.value\n        }\n\n        case 'throw': {\n          throw action.value\n        }\n\n        case 'resolve': {","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/integrations/mock/when.ts#L312-L348","documentation":"When a `vi.when` chain is created with `{ onUnmatched: 'throw' }`, calling the spy with arguments that match no registered `.calledWith(...)` behavior throws this error listing the unmatched arguments. This is an opt-in strict mode that surfaces unexpected calls during the test rather than silently returning undefined or falling through to the original implementation.","triggerScenarios":"Creating `vi.when(spy, { onUnmatched: 'throw' })`, registering behaviors for some argument sets, then invoking `spy(...)` with arguments that deep-equal none of the registered `calledWith` sets.","commonSituations":"Forgetting to register a behavior for a code path the test exercises, argument shape mismatches (e.g. passing a string where `calledWith` registered a number), or stale matchers after a refactor.","solutions":["Add a `vi.when(spy).calledWith(<unmatched args>).thenReturn(...)` for the call shown in the error message.","Fix the call site to pass the arguments you actually intended to match.","If unmatched calls are acceptable, drop `onUnmatched: 'throw'` (or set `'passthrough'`) to fall back to the original implementation."],"exampleFix":"// before\nvi.when(spy, { onUnmatched: 'throw' }).calledWith(1).thenReturn('a')\nspy(2) // throws: no behavior defined when called with [2]\n// after\nvi.when(spy, { onUnmatched: 'throw' })\n  .calledWith(1).thenReturn('a')\nvi.when(spy).calledWith(2).thenReturn('b')\nspy(2) // 'b'","handlingStrategy":"try-catch","validationCode":"// only opt into onUnmatched:'throw' after registering all expected calls\nconst w = vi.when(spy) // default 'passthrough' first\nw.calledWith(1).thenReturn('a')\n// switch to strict only when coverage is complete, or assert via .toHaveBeenExhausted()","typeGuard":null,"tryCatchPattern":"try {\n  spy(unexpectedArg)\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('vi.when: no behavior defined')) {\n    // register the missing behavior or fix the call site\n  } else throw e\n}","preventionTips":["Register behaviors for every call path the test exercises before using `onUnmatched: 'throw'`.","Use `.toHaveBeenExhausted()` to verify all behaviors were consumed instead of relying solely on strict mode."],"tags":["mock","vi-when","strict-mode","matcher"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}