jestjs/jest · error · TypeError

`jest.advanceTimersByTimeAsync()` is not available when usin

Error message

`jest.advanceTimersByTimeAsync()` is not available when using legacy fake timers.

What it means

TypeError thrown by `jest.advanceTimersByTimeAsync()` when the active fake timer implementation is the legacy one (`this.environment.fakeTimers`), not the modern one. The async timer APIs only exist on `@jest/fake-timers`' modern implementation, so calling them under legacy fake timers is unsupported.

Source

Thrown at packages/jest-runtime/src/internals/JestGlobals.ts:303

      this.environment.global[logErrorsBeforeRetrySymbol] =
        options?.logErrorsBeforeRetry;
      this.environment.global[waitBeforeRetrySymbol] = options?.waitBeforeRetry;
      this.environment.global[retryImmediatelySymbol] =
        options?.retryImmediately;

      return jestObject;
    };

    const jestObject: Jest = {
      advanceTimersByTime: msToRun =>
        _getFakeTimers().advanceTimersByTime(msToRun),
      advanceTimersByTimeAsync: async msToRun => {
        const fakeTimers = _getFakeTimers();

        if (fakeTimers === this.environment.fakeTimersModern) {
          await fakeTimers.advanceTimersByTimeAsync(msToRun);
        } else {
          throw new TypeError(
            '`jest.advanceTimersByTimeAsync()` is not available when using legacy fake timers.',
          );
        }
      },
      advanceTimersToNextFrame: () => {
        const fakeTimers = _getFakeTimers();

        if (fakeTimers === this.environment.fakeTimersModern) {
          return fakeTimers.advanceTimersToNextFrame();
        }
        throw new TypeError(
          '`jest.advanceTimersToNextFrame()` is not available when using legacy fake timers.',
        );
      },
      advanceTimersToNextTimer: steps =>
        _getFakeTimers().advanceTimersToNextTimer(steps),
      advanceTimersToNextTimerAsync: async steps => {
        const fakeTimers = _getFakeTimers();

View on GitHub (pinned to f49721c78e)

Solutions

  1. Switch to modern fake timers: `jest.useFakeTimers({ legacyFakeTimers: false })` (or remove the option — modern is default).
  2. If you must keep legacy timers, use the sync `jest.advanceTimersByTime(ms)` instead of the async variant.
  3. Remove `fakeTimers: { legacyFakeTimers: true }` from jest.config unless you have a specific reason.

Example fix

// before
jest.useFakeTimers({ legacyFakeTimers: true });
await jest.advanceTimersByTimeAsync(1000); // throws

// after
jest.useFakeTimers(); // modern (default)
await jest.advanceTimersByTimeAsync(1000);
Defensive patterns

Strategy: validation

Validate before calling

// Detect which timer backend is active before calling async timer APIs
function isLegacyTimers() {
  // legacyFakeTimers is set via config or useFakeTimers; track it yourself:
  return Boolean(globalThis.__LEGACY_FAKE_TIMERS__);
}
if (!isLegacyTimers()) {
  await jest.advanceTimersByTimeAsync(1000);
} else {
  jest.advanceTimersByTime(1000);
}

Prevention

When it happens

Trigger: Calling `jest.advanceTimersByTimeAsync(ms)` after enabling legacy fake timers via `jest.useFakeTimers({ legacyFakeTimers: true })` or having `fakeTimers.legacyFakeTimers: true` in jest config.

Common situations: Inheriting a config with `fakeTimers: { legacyFakeTimers: true }`; explicitly opting into legacy timers for a specific behavior then forgetting and calling an async timer method; upgrading Jest and finding old tests relied on legacy timers.

Related errors


AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03). Data as JSON: /data/errors/8a08a123070fa44e.json. Report an issue: GitHub.