{"record":{"id":"94852e5af0d1f940","repo":"microsoft/playwright","slug":"no-tab-found-for-sessionid-sessionid","errorCode":null,"errorMessage":"No tab found for sessionId: ${sessionId}","messagePattern":"No tab found for sessionId: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/tools/mcp/browserModel.ts","lineNumber":192,"sourceCode":"      method,\n      params,\n    ]);\n  }\n\n  // Forward a CDP command from Playwright to the tab its sessionId resolves to.\n  async sendCommand(sessionId: string, method: string, params: any): Promise<any> {\n    // Two cases:\n    // 1. sessionId is a relay-level tab session (pw-tab-N) → strip and route by tabId.\n    // 2. sessionId is a child CDP session (worker, oopif) → route to its owning tab,\n    //    keep the sessionId so the extension forwards it to chrome.debugger.\n    let tabSession = this._findTabSession(s => s.sessionId === sessionId);\n    let cdpSessionId: string | undefined;\n    if (!tabSession) {\n      tabSession = this._findTabSession(s => s.childSessions.has(sessionId));\n      cdpSessionId = sessionId;\n    }\n    if (!tabSession)\n      throw new Error(`No tab found for sessionId: ${sessionId}`);\n    return await this._sendToExtension('chrome.debugger.sendCommand', [\n      { tabId: tabSession.tabId, sessionId: cdpSessionId },\n      method,\n      params,\n    ]);\n  }\n\n  // ─── Internals ────────────────────────────────────────────────────────\n\n  private async _attachTab(tabId: number): Promise<TabSession> {\n    const existing = this._tabSessions.get(tabId);\n    if (existing)\n      return existing;\n    await this._sendToExtension('chrome.debugger.attach', [{ tabId }, '1.3']);\n    const result = await this._sendToExtension('chrome.debugger.sendCommand', [\n      { tabId },\n      'Target.getTargetInfo',\n    ]);","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/tools/mcp/browserModel.ts#L174-L210","documentation":"Thrown by the extension browser model's `sendCommand` when a `sessionId` matches neither a relay-level tab session (`pw-tab-N`) nor any tab session's set of child CDP sessions (workers, oopifs). The relay cannot route a CDP command whose session it does not recognize, so it aborts.","triggerScenarios":"Playwright sends a CDP command on a sessionId that was never created (typo/foreign id), that belonged to a tab already detached/closed, or to a child session (worker/oopif) whose owning tab has been detached. The two-step lookup (`_findTabSession` by sessionId, then by `childSessions.has`) both fail.","commonSituations":"A child session (service worker, out-of-process iframe) was destroyed but Playwright still holds its sessionId and sends a command; the extension detached a tab mid-operation; protocol version drift between Playwright and the extension producing session ids the relay didn't record.","solutions":["Recover by re-attaching the target (navigate/reattach the tab) so a fresh sessionId is issued.","Confirm the extension connection is healthy and the target tab is still attached.","Treat stale-session commands as non-fatal: drop the command and re-issue after re-attach rather than retrying the same id."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await model.sendCommand(sessionId, method, params);\n} catch (e) {\n  if (/No tab found for sessionId/.test((e as Error).message)) {\n    // session is gone — re-attach the target to obtain a fresh sessionId, then drop the command\n    return; // or re-issue after re-attach\n  }\n  throw e;\n}","preventionTips":["Drop stale sessionIds when targets detach; re-attach to get fresh ones.","Treat 'No tab found' as a recoverable signal, not a fatal error.","Keep extension and Playwright versions aligned to avoid session-id drift."],"tags":["extension","cdp","session","browser-model","routing"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}