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

  1. Use exactly one of the literals: `'manual'`, `'nextTimerAsync'`, or `'interval'`.
  2. If using TypeScript, type the parameter as the union `'manual' | 'nextTimerAsync' | 'interval'` so the compiler rejects invalid values.
  3. 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

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


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/f81b34ec24cefcc4. Report an issue: GitHub.