vitest-dev/vitest · error · Error
Invalid tick mode: ${mode}
Error message
Invalid tick mode: ${mode} What it means
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.
Source
Thrown at packages/vitest/src/integrations/mock/timers.ts:245
return this._clock.countTimers()
}
return 0
}
setTimerTickMode(mode: 'manual' | 'nextTimerAsync' | 'interval', interval?: number): void {
if (this._checkFakeTimers()) {
if (mode === 'manual') {
this._clock.setTickMode({ mode: 'manual' })
}
else if (mode === 'nextTimerAsync') {
this._clock.setTickMode({ mode: 'nextAsync' })
}
else if (mode === 'interval') {
this._clock.setTickMode({ mode: 'interval', delta: interval })
}
else {
throw new Error(`Invalid tick mode: ${mode}`)
}
}
}
configure(config: FakeTimersConfig): void {
this._userConfig = config
}
isFakeTimers(): boolean {
return this._fakingTime
}
private _checkFakeTimers() {
if (!this._fakingTime) {
throw new Error(
'A function to advance timers was called but the timers APIs are not mocked. '
+ 'Call `vi.useFakeTimers()` in the test file first.',
)View on GitHub (pinned to 1fa9837ec2)
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.
Example fix
// before
timers().setTimerTickMode('manual ')
// after
timers().setTimerTickMode('manual') Defensive patterns
Strategy: type-guard
Validate before calling
const VALID_MODES = new Set(['manual', 'nextTimerAsync', 'interval'])
function safeSetTickMode(mode, interval) {
if (!VALID_MODES.has(mode)) throw new Error(`Invalid tick mode: ${mode}`)
timers().setTimerTickMode(mode, interval)
} Type guard
function isTickMode(v): v is 'manual' | 'nextTimerAsync' | 'interval' {
return v === 'manual' || v === 'nextTimerAsync' || v === 'interval'
} Prevention
- 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.
When it happens
Trigger: 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`.
Common situations: 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.
Related errors
- A function to advance timers was called but the timers APIs
- Invalid command name "${name}". Only alphanumeric characters
- Invalid command name "${command}". Only alphanumeric charact
- ${name}Browser name is required. Please, set `test.browser.i
- SchemaMatching expected to receive a Standard Schema.
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/f81b34ec24cefcc4.
Report an issue: GitHub.