microsoft/playwright · error · Error

Cannot start tracing while stopping

Error message

Cannot start tracing while stopping

What it means

The Tracing.start() method refuses to run while a previous stopChunk() is still flushing trace data to disk (the _isStopping flag is set). Tracing has an asynchronous teardown window between stopChunk being called and the chunk file being sealed; starting a new trace inside that window would race with file writes. This guard prevents interleaved chunk state.

Source

Thrown at packages/playwright-core/src/server/trace/recorder/tracing.ts:152

      this._contextCreatedEvent.options = context._options;
    }
  }

  private _sdkLanguage() {
    return this._context instanceof BrowserContext ? this._context._browser.sdkLanguage() : this._context.attribution.playwright.options.sdkLanguage;
  }

  async resetForReuse(progress: Progress) {
    // Discard previous chunk if any and ignore any errors there.
    await this.stopChunk(progress, { mode: 'discard' }).catch(() => {});
    await progress.race(this._stop());
    if (this._snapshotter)
      await progress.race(this._snapshotter.resetForReuse());
  }

  start(progress: Progress, options: TracerOptions) {
    if (this._isStopping)
      throw new Error('Cannot start tracing while stopping');
    if (this._state)
      throw new Error('Tracing has been already started');

    // Re-write for testing.
    this._contextCreatedEvent.sdkLanguage = this._sdkLanguage();

    // TODO: passing the same name for two contexts makes them write into a single file
    // and conflict.
    const traceName = options.name || createGuid();

    const tracesDir = this._createTracesDirIfNeeded();

    // Init the state synchronously.
    this._state = {
      options,
      traceName,
      tracesDir,
      traceFile: path.join(tracesDir, traceName + '.trace'),

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Await the full tracing lifecycle: call tracing.stop() (or await the chunk completion) before calling tracing.start() again.
  2. If reproducing in the test runner, move tracing.start into a serial hook and ensure no parallel worker touches the same context's tracing.
  3. Add a small await on the context's reuse/reset promise so _isStopping has cleared before you start.

Example fix

// before
await context.tracing.stopChunk({ path: 't.zip' });
await context.tracing.start({ snapshots: true }); // may hit _isStopping

// after
await context.tracing.stopChunk({ path: 't.zip' });
await context.tracing.stop();
await context.tracing.start({ snapshots: true });
Defensive patterns

Strategy: validation

Validate before calling

// Avoid calling start while a chunk teardown is in flight.
// Track an in-progress flag yourself if you orchestrate tracing:
let stopping = false;
async function safeStart(ctx, opts) {
  if (stopping) throw new Error('teardown in progress');
  // ensure prior trace is fully stopped
  await ctx.tracing.stop().catch(() => {});
  await ctx.tracing.start(opts);
}

Try / catch

try {
  await context.tracing.start(opts);
} catch (e) {
  if (/while stopping/.test(String(e.message))) {
    await context.tracing.stop().catch(() => {});
    await context.tracing.start(opts);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling context.tracing.start(...) immediately after context.tracing.stopChunk(...) resolves, but before the internal _isStopping flag clears (e.g. the discard in resetForReuse or a manual chunk cycle). Also when two callers (e.g. test runner reuse + user code) invoke tracing.start concurrently.

Common situations: Re-enabling tracing inside a beforeEach/test that races with the runner's own tracing teardown; calling tracing.start in parallel from multiple test workers sharing a context; chaining start right after stopChunk({mode:'discard'}) without awaiting the full stop.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/03a2f28765df55f2. Report an issue: GitHub.