{"record":{"id":"dcfb0a37d2008828","repo":"musistudio/claude-code-router","slug":"this-browser-automation-session-is-observeonly-and","errorCode":null,"errorMessage":"This browser automation session is observeOnly and cannot mutate browser state.","messagePattern":"This browser automation session is observeOnly and cannot mutate browser state\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/electron/src/main/browser-automation-mcp.ts","lineNumber":1246,"sourceCode":"      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 {\n    if (session?.observeOnly) {\n      throw new Error(\"This browser automation session is observeOnly and cannot mutate browser state.\");\n    }\n  }\n\n  private removeSessionsForTab(tabId: string): void {\n    for (const [sessionId, session] of this.sessions) {\n      if (session.ref.tabId === tabId) {\n        this.sessions.delete(sessionId);\n      }\n    }\n    for (const [subscriptionId, subscription] of this.subscriptions) {\n      if (subscription.ref?.tabId === tabId) {\n        subscription.unsubscribe();\n        this.subscriptions.delete(subscriptionId);\n      }\n    }\n  }\n\n  private subscribeEvents(args: Record<string, unknown>): unknown {","sourceCodeStart":1228,"sourceCodeEnd":1264,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/electron/src/main/browser-automation-mcp.ts#L1228-L1264","documentation":"Thrown by assertCanMutate when a tool that changes browser state (navigate, close tab, click, type, etc.) is invoked with a session whose observeOnly flag is true. Observe-only sessions are limited to read-only operations like snapshots and screenshots by design.","triggerScenarios":"Calling a mutating tool (e.g. browser_navigate, browser_tab_close) with a session that was attached with observeOnly: true.","commonSituations":"A monitoring/audit integration intentionally attaches read-only but a later step tries to act; the observeOnly flag defaulted on unexpectedly in session setup.","solutions":["Attach a non-observe-only session (observeOnly: false / omitted) for mutating operations.","Split your workflow: read via the observe-only session, mutate via a full session.","Check the session's observeOnly flag before dispatching mutating tools."],"exampleFix":"// before\nconst { session } = await call(\"browser_attach\", { tabId, observeOnly: true });\nawait call(\"browser_navigate\", { url, session });\n\n// after\nconst { session } = await call(\"browser_attach\", { tabId });\nawait call(\"browser_navigate\", { url, session });","handlingStrategy":"validation","validationCode":"if (session.observeOnly && MUTATING_TOOLS.includes(toolName)) { const { session: rw } = await call(\"browser_attach\", { tabId: session.ref.tabId }); session = rw; }\nawait call(toolName, { ...args, session });","typeGuard":"function isMutableSession(s: { observeOnly?: boolean } | undefined): boolean { return !s?.observeOnly; }","tryCatchPattern":"try { await call(toolName, args); } catch (e) { if (e instanceof Error && e.message.includes(\"observeOnly\")) { /* attach a non-observe-only session and retry */ } else throw e; }","preventionTips":["Attach read-write sessions for action workflows","Keep observeOnly strictly for monitoring","Check flags before dispatching mutating tools"],"tags":["mcp","browser-automation","permissions","observe-only"],"backgroundTag":"read-only-session-permission","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}