claude-code - 💡(How to fix) Fix [BUG] Chrome extension: permanent disconnect after CDP operations — 6 months unfixed, 7+ closed issues, root cause identified with proposed fix [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#47849Fetched 2026-04-15 06:40:35
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
2
Author
Participants
Timeline (top)
labeled ×4commented ×1

Error Message

The retry logic handles "debugger is not attached" (pre-command check) but NOT "Detached while handling command" (mid-command failure). Different error strings, only the first is caught. port.onDisconnect clears state but never attempts reconnection. Once the port drops (from the error cascade of Bug 1+2), the connection is permanently dead. 4. sendCommand retry doesn't match this error string → unhandled 5. Error propagates, native messaging port disconnects const msg = error.message.toLowerCase(); const error = chrome.runtime.lastError?.message; if (error?.includes("native messaging host not found")) return;

Root Cause

This bug has been reported 7+ times over 6 months and auto-closed every time — none were fixed. All prior issues are now locked. This consolidation includes a root cause analysis at the extension code level and a proposed 30-line fix.

Code Example

chrome.debugger.onDetach.addListener((source, reason) => {
  const tabId = source.tabId;
  // Mark debugger as detached, reject pending promises, clean up CDP state
});

---

const msg = error.message.toLowerCase();
if (msg.includes("not attached") || msg.includes("detached")) {
  await this.attachDebugger(tabId);
  continue; // retry
}

---

port.onDisconnect.addListener(() => {
  const error = chrome.runtime.lastError?.message;
  port = null; connected = false;
  if (error?.includes("native messaging host not found")) return;
  const delay = Math.min(3000 * Math.pow(2, reconnectAttempt++), 60000);
  setTimeout(() => connectToNativeHost(), delay);
});
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

Why this is filed as a new issue

This bug has been reported 7+ times over 6 months and auto-closed every time — none were fixed. All prior issues are now locked. This consolidation includes a root cause analysis at the extension code level and a proposed 30-line fix.

Prior issues (all closed, none resolved):

  • #15463 — Chrome native host enters zombie state (root, NOT_PLANNED)
  • #15743 — Extension disconnects during screenshot/JS operations (dupe of #15463)
  • #24217 — Extension doesn't reconnect after native messaging disconnect (NOT_PLANNED)
  • #25518 — Debugger detaches on complex pages (NOT_PLANNED)
  • #28013 — Permanent disconnect after screenshot/scroll (dupe, our root cause analysis)
  • #42223 — (different bug, correctly duped)

Multiple users across all platforms (macOS, Linux, Windows) confirm this is still broken.

What's Wrong?

The Chrome extension permanently disconnects after CDP-based operations (screenshot, scroll, coordinate click). Once disconnected, it enters an infinite exponential backoff reconnection loop and never recovers. Only a full Chrome restart resolves it.

Stable tools (content script API): navigate, read_page, find, form_input, javascript_tool — all work reliably.

Unstable tools (debugger/CDP API): screenshot, scroll, coordinate-based left_click, gif_creator export — trigger permanent disconnect.

Root Cause (Extension Code Level)

Examined extension source at ~/.config/google-chrome/Default/Extensions/fcoeoabgfenejglbffodgkkbkcdhcgfn/1.0.59_0/. Three compounding bugs:

Bug 1: Missing chrome.debugger.onDetach listener

The extension registers chrome.debugger.onEvent but never registers chrome.debugger.onDetach. Zero references to onDetach in the entire extension codebase.

When Chrome detaches the debugger mid-operation (page navigation, iframe changes, resource pressure), the extension doesn't know. The next sendCommand fails with "Detached while handling command."

Bug 2: sendCommand retry gap

The retry logic handles "debugger is not attached" (pre-command check) but NOT "Detached while handling command" (mid-command failure). Different error strings, only the first is caught.

Bug 3: Native messaging port has zero reconnection logic

port.onDisconnect clears state but never attempts reconnection. Once the port drops (from the error cascade of Bug 1+2), the connection is permanently dead.

The Cascade

  1. Page.captureScreenshot on complex page takes 20s+
  2. Chrome detaches debugger mid-operation (no onDetach listener)
  3. CDP response arrives with "Detached while handling command"
  4. sendCommand retry doesn't match this error string → unhandled
  5. Error propagates, native messaging port disconnects
  6. onDisconnect fires → state cleared → no reconnection
  7. All subsequent tool calls fail permanently

Proposed Fix (~30 lines across 3 locations)

Fix 1 — Add onDetach listener:

chrome.debugger.onDetach.addListener((source, reason) => {
  const tabId = source.tabId;
  // Mark debugger as detached, reject pending promises, clean up CDP state
});

Fix 2 — Extend sendCommand retry:

const msg = error.message.toLowerCase();
if (msg.includes("not attached") || msg.includes("detached")) {
  await this.attachDebugger(tabId);
  continue; // retry
}

Fix 3 — Add reconnection to onDisconnect:

port.onDisconnect.addListener(() => {
  const error = chrome.runtime.lastError?.message;
  port = null; connected = false;
  if (error?.includes("native messaging host not found")) return;
  const delay = Math.min(3000 * Math.pow(2, reconnectAttempt++), 60000);
  setTimeout(() => connectToNativeHost(), delay);
});

Environment

  • Chrome: 133+ (tested on Linux, reports confirm macOS and Windows)
  • Claude Code: 2.1.83+
  • Extension: 1.0.59+
  • Confirmed across native messaging AND WebSocket bridge paths

Impact

Browser automation is Claude Code's differentiator over other AI coding tools. This bug makes CDP-based operations (screenshot, scroll, coordinate actions) unreliable to unusable. Multiple users (#24217, #25518, #28013) have reported it as "extension is unusable."

The fix is small, backward-compatible, and addresses the root cause rather than working around symptoms. Happy to submit a PR if the extension source is available.

extent analysis

TL;DR

The proposed fix involves adding an onDetach listener, extending the sendCommand retry logic, and implementing reconnection logic for the native messaging port to resolve the permanent disconnection issue after CDP-based operations.

Guidance

  • Implement the proposed fixes: add an onDetach listener to handle debugger detachment, extend the sendCommand retry logic to catch "Detached while handling command" errors, and add reconnection logic to the onDisconnect event of the native messaging port.
  • Verify the fixes by testing CDP-based operations (screenshot, scroll, coordinate actions) and checking if the extension recovers from disconnections without requiring a full Chrome restart.
  • Review the extension code to ensure the fixes are applied correctly and do not introduce any new issues.
  • Test the fixes across different platforms (macOS, Linux, Windows) and Chrome versions to ensure compatibility.

Example

The proposed fix includes code snippets for the three required changes:

// Fix 1: Add onDetach listener
chrome.debugger.onDetach.addListener((source, reason) => {
  const tabId = source.tabId;
  // Mark debugger as detached, reject pending promises, clean up CDP state
});

// Fix 2: Extend sendCommand retry
const msg = error.message.toLowerCase();
if (msg.includes("not attached") || msg.includes("detached")) {
  await this.attachDebugger(tabId);
  continue; // retry
}

// Fix 3: Add reconnection to onDisconnect
port.onDisconnect.addListener(() => {
  const error = chrome.runtime.lastError?.message;
  port = null; connected = false;
  if (error?.includes("native messaging host not found")) return;
  const delay = Math.min(3000 * Math.pow(2, reconnectAttempt++), 60000);
  setTimeout(() => connectToNativeHost(), delay);
});

Notes

The proposed fixes address the root cause of the issue, but it is essential to thoroughly test the changes to ensure they do not introduce any new problems. Additionally, the fixes should be reviewed and verified by the extension maintainers to ensure they are compatible with the existing codebase.

Recommendation

Apply the proposed workaround by implementing the three fixes (adding an onDetach listener, extending the sendCommand retry logic, and adding reconnection logic to the onDisconnect event) to resolve the permanent disconnection issue after CDP-based operations. This approach addresses the root cause of the problem and provides a reliable solution.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] Chrome extension: permanent disconnect after CDP operations — 6 months unfixed, 7+ closed issues, root cause identified with proposed fix [1 comments, 2 participants]