{"record":{"id":"f81b34ec24cefcc4","repo":"vitest-dev/vitest","slug":"invalid-tick-mode-mode","errorCode":null,"errorMessage":"Invalid tick mode: ${mode}","messagePattern":"Invalid tick mode: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/integrations/mock/timers.ts","lineNumber":245,"sourceCode":"      return this._clock.countTimers()\n    }\n\n    return 0\n  }\n\n  setTimerTickMode(mode: 'manual' | 'nextTimerAsync' | 'interval', interval?: number): void {\n    if (this._checkFakeTimers()) {\n      if (mode === 'manual') {\n        this._clock.setTickMode({ mode: 'manual' })\n      }\n      else if (mode === 'nextTimerAsync') {\n        this._clock.setTickMode({ mode: 'nextAsync' })\n      }\n      else if (mode === 'interval') {\n        this._clock.setTickMode({ mode: 'interval', delta: interval })\n      }\n      else {\n        throw new Error(`Invalid tick mode: ${mode}`)\n      }\n    }\n  }\n\n  configure(config: FakeTimersConfig): void {\n    this._userConfig = config\n  }\n\n  isFakeTimers(): boolean {\n    return this._fakingTime\n  }\n\n  private _checkFakeTimers() {\n    if (!this._fakingTime) {\n      throw new Error(\n        'A function to advance timers was called but the timers APIs are not mocked. '\n        + 'Call `vi.useFakeTimers()` in the test file first.',\n      )","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/integrations/mock/timers.ts#L227-L263","documentation":"Thrown by `FakeTimers.setTimerTickMode()` when the `mode` argument is not one of the three accepted string literals: `'manual'`, `'nextTimerAsync'`, or `'interval'`. The error is the exhaustiveness fallback inside the if/else chain; it is also gated by `_checkFakeTimers()`, so fake timers must already be active.","triggerScenarios":"Calling `vi.setConfig`/timers API `setTimerTickMode(mode)` with a typo (e.g. `'manual '` with a trailing space), a value from a variable that resolved to an unexpected string, or `undefined`.","commonSituations":"Typo in the mode string; passing a numeric mode; dynamically computing the mode and producing an out-of-set value; using an outdated mode name after a Vitest upgrade.","solutions":["Use exactly one of the literals: `'manual'`, `'nextTimerAsync'`, or `'interval'`.","If using TypeScript, type the parameter as the union `'manual' | 'nextTimerAsync' | 'interval'` so the compiler rejects invalid values.","Log the actual `mode` value before the call to catch whitespace/casing issues."],"exampleFix":"// before\ntimers().setTimerTickMode('manual ')\n\n// after\ntimers().setTimerTickMode('manual')","handlingStrategy":"type-guard","validationCode":"const VALID_MODES = new Set(['manual', 'nextTimerAsync', 'interval'])\nfunction safeSetTickMode(mode, interval) {\n  if (!VALID_MODES.has(mode)) throw new Error(`Invalid tick mode: ${mode}`)\n  timers().setTimerTickMode(mode, interval)\n}","typeGuard":"function isTickMode(v): v is 'manual' | 'nextTimerAsync' | 'interval' {\n  return v === 'manual' || v === 'nextTimerAsync' || v === 'interval'\n}","tryCatchPattern":null,"preventionTips":["Type the mode parameter as the literal union so TypeScript rejects invalid values.","Keep a constant set of valid modes and validate against it before calling.","Avoid computing the mode dynamically; if you do, log it before the call."],"tags":["fake-timers","settimertickmode","validation","api-misuse"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}