{"record":{"id":"870a0d2f658ddb50","repo":"musistudio/claude-code-router","slug":"browser-automation-session-tabid-does-not-match-th","errorCode":null,"errorMessage":"Browser automation session tabId does not match the attached session.","messagePattern":"Browser automation session tabId does not match the attached session\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/electron/src/main/browser-automation-mcp.ts","lineNumber":1226,"sourceCode":"  }\n\n  private requireSession(args: Record<string, unknown>): AttachedSession {\n    const session = this.resolveOptionalSession(args);\n    if (!session) {\n      throw new Error(\"A valid browser automation session is required.\");\n    }\n    return session;\n  }\n\n  private resolveOptionalSession(args: Record<string, unknown>): AttachedSession | undefined {\n    const ref = readSessionRef(args.session);\n    if (!ref) {\n      return undefined;\n    }\n    const existing = this.sessions.get(ref.sessionId);\n    if (existing) {\n      if (existing.ref.tabId !== ref.tabId) {\n        throw new Error(\"Browser automation session tabId does not match the attached session.\");\n      }\n      return existing;\n    }\n    const state = builtInBrowserService.getAutomationState();\n    if (!state.tabs.some((tab) => tab.id === ref.tabId)) {\n      throw new Error(`Browser automation session tab was not found: ${ref.tabId}`);\n    }\n    const restored: AttachedSession = {\n      attachedAt: Date.now(),\n      leaseId: randomUUID(),\n      observeOnly: false,\n      ref\n    };\n    this.sessions.set(ref.sessionId, restored);\n    return restored;\n  }\n\n  private assertCanMutate(session?: AttachedSession): void {","sourceCodeStart":1208,"sourceCodeEnd":1244,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/electron/src/main/browser-automation-mcp.ts#L1208-L1244","documentation":"Thrown when reusing a known sessionId whose stored attached session points at a different tabId than the ref in the current request. Sessions are pinned to one tab; the mismatch guard prevents a stale or hand-edited session ref from silently retargeting an established session to another tab.","triggerScenarios":"Calling a tool with { session: { sessionId, tabId } } where tabId differs from the tabId recorded when the session was created — e.g. copying a session object and swapping only the tabId.","commonSituations":"Scripts try to migrate a session to a new tab by editing the ref instead of creating a new session; a tab was closed and recreated with the caller guessing a new id under the same sessionId.","solutions":["Keep the session object unchanged from what the attach call returned.","To operate on a different tab, create/attach a new session for that tabId.","After a tab closes (sessions for it are removed), re-attach fresh rather than mutating the old ref."],"exampleFix":"// before\nawait call(\"browser_tool\", { session: { sessionId, tabId: otherTabId } });\n\n// after\nconst { session: sessionB } = await call(\"browser_attach\", { tabId: otherTabId });\nawait call(\"browser_tool\", { session: sessionB });","handlingStrategy":"validation","validationCode":"if (session.ref.tabId !== desiredTabId) { const fresh = await call(\"browser_attach\", { tabId: desiredTabId }); session = fresh.session; }\nawait call(tool, { session });","typeGuard":null,"tryCatchPattern":"try { await call(tool, { session }); } catch (e) { if (e instanceof Error && e.message.includes(\"does not match the attached session\")) { const { session: s } = await call(\"browser_attach\", { tabId: session.ref.tabId }); await call(tool, { session: s }); } else throw e; }","preventionTips":["Never hand-edit session refs","Create a new session per tab","Store the session object as opaque"],"tags":["mcp","browser-automation","session","stale-reference"],"backgroundTag":"session-tab-mismatch","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}