microsoft/playwright · error · Error

Unknown target: ${targetId}

Error message

Unknown target: ${targetId}

What it means

_onDispatchMessageFromTarget routes incoming target-session messages to one of: the provisional page, the main session, or a known frame session. If targetId matches none of these, the message cannot be routed and the dispatcher throws. This indicates an out-of-band or unexpected target session id from the WebKit target dispatcher.

Source

Thrown at packages/playwright-core/src/server/webkit/wkPage.ts:375

      this._provisionalPage = new WKProvisionalPage(session, this);
      if (targetInfo.isPaused) {
        this._provisionalPage.initializationPromise.then(() => {
          this._pageProxySession.sendMayFail('Target.resume', { targetId: targetInfo.targetId });
        });
      }
    }
  }

  private _onDispatchMessageFromTarget(event: Protocol.Target.dispatchMessageFromTargetPayload) {
    const { targetId, message } = event;
    if (this._provisionalPage && this._provisionalPage._session.sessionId === targetId)
      this._provisionalPage._session.dispatchMessage(JSON.parse(message));
    else if (this._session.sessionId === targetId)
      this._session.dispatchMessage(JSON.parse(message));
    else if (this._targetIdToFrameSession.has(targetId))
      this._targetIdToFrameSession.get(targetId)!._session.dispatchMessage(JSON.parse(message));
    else
      throw new Error('Unknown target: ' + targetId);
  }

  private _addSessionListeners() {
    this._sessionListeners = [
      eventsHelper.addEventListener(this._session, 'Page.frameNavigated', event => this._onFrameNavigated(event.frame, false)),
      eventsHelper.addEventListener(this._session, 'Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url)),
      eventsHelper.addEventListener(this._session, 'Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId)),
      eventsHelper.addEventListener(this._session, 'Page.frameDetached', event => this._onFrameDetached(event.frameId)),
      eventsHelper.addEventListener(this._session, 'Page.willCheckNavigationPolicy', event => this._onWillCheckNavigationPolicy(event.frameId)),
      eventsHelper.addEventListener(this._session, 'Page.didCheckNavigationPolicy', event => this._onDidCheckNavigationPolicy(event.frameId, event.cancel)),
      eventsHelper.addEventListener(this._session, 'Page.loadEventFired', event => this._page.frameManager.frameLifecycleEvent(event.frameId, 'load')),
      eventsHelper.addEventListener(this._session, 'Page.domContentEventFired', event => this._page.frameManager.frameLifecycleEvent(event.frameId, 'domcontentloaded')),
      eventsHelper.addEventListener(this._session, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)),
      eventsHelper.addEventListener(this._session, 'Runtime.bindingCalled', event => this._onBindingCalled(event.contextId, event.argument)),
      eventsHelper.addEventListener(this._session, 'Console.messageAdded', event => this._onConsoleMessage(event)),
      eventsHelper.addEventListener(this._session, 'Console.messageRepeatCountUpdated', event => this._onConsoleRepeatCountUpdated(event)),
      eventsHelper.addEventListener(this._pageProxySession, 'Dialog.javascriptDialogOpening', event => this._onDialog(event)),
      eventsHelper.addEventListener(this._pageProxySession, 'Dialog.javascriptDialogClosed', () => this._onDialogClosed()),

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. If seen intermittently during teardown, it is usually a benign race; ensure your test awaits close/navigation fully before exiting.
  2. Reduce rapid open/close of cross-origin iframes to avoid late target messages.
  3. If reproducible on stable flows, report to Playwright with a trace — it indicates a target-tracking gap in wkPage.
Defensive patterns

Strategy: try-catch

Type guard

null

Try / catch

// Internal dispatcher; if surfaced, log and continue — late target messages are benign during teardown.
try { await page.goto(url); }
catch (e) { if (/Unknown target/.test(e.message)) { /* retry or ignore on teardown */ } else throw e; }

Prevention

When it happens

Trigger: A protocol message arrives for a target whose session was never registered (or already torn down): late messages for a closed iframe target, OOPIF target race during teardown, or a target created by an extension/portal path not tracked by _targetIdToFrameSession.

Common situations: Mostly an internal/protocol race, not directly user-caused. Surfaces under heavy cross-origin iframe churn, COOP/COEP, or rapid navigation+close sequences. If reproducible it points to a missing target lifecycle handler.

Related errors


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