Tencent / Tencent/BrowserSkill

chrome.debugger wedges for all profiles once a second profile connects (Yandex Browser 26.8, bsk 0.3.0)

Open
#272 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
5.7k
Forks
399
Avg merge
2d 9h
Merged PRs (30d)
74

Description

Summary

With one connected browser everything works. As soon as the extension connects from a second profile of the same browser, CDP breaks and stays broken:

error: browser rejected the underlying CDP call
hint: confirm the tab is still in a loaded state and retry; reloading the tab usually resets a stuck DevTools session
details: Debugger is not attached to the tab with id: <id>

bsk browsers still lists the instance(s), bsk doctor is all ok, non‑CDP calls still work (bsk tab list returns tabs), but navigate / observe / snapshot / screenshot / evaluate all fail. The wedge is sticky: disconnecting (or disabling) the second profile's extension does not recover the first one — only a full browser restart does, and it breaks again the next time a second instance connects.

Environment

  • macOS 26.6.2 (Apple Silicon)
  • Yandex Browser 26.8.0.1829, reports itself to the extension as chrome 150.0.0.0
  • bsk CLI 0.3.0 (aarch64-apple-darwin, release checksum verified), daemon 0.3.0, extension 0.3.0 (browser-skill-extension-v0.3.0-chrome.zip), daemon protocol 1.3, extension protocol 1.3, version_skew: false
  • Extension installed unpacked (chrome://extensions → Load unpacked) in two profiles of the same browser: profile A (Default) and profile B (Profile 2)
  • Daemon ws://127.0.0.1:52800, BSK_HOME=~/.bsk
  • Yandex serves both profiles from a single browser process (one main process, no --profile-directory in its argv) — unlike Chrome, which runs a separate process per profile. Both extension instances therefore have the same extension id (onnlggadnmhcabfamiocjghebiollidk, unpacked) inside one browser process.

Reproduction (two independent cycles, observed)

  1. Install the unpacked extension in profile A only. bsk doctor → all ok, 1 browser(s) connected.
  2. First-use flow works:
    bsk session start --no-focus --browser <A> --json    # session_id, agent_window_id
    bsk navigate https://example.com --session <id>      # tab=… reached=load
    bsk observe --session <id>                           # RootWebArea "Example Domain" + text
    bsk session stop <id>                                # ok
    
  3. Connect the same extension build in profile B. bsk doctor → all ok, 2 browser(s) connected.
  4. Repeat step 2 against either instance (--browser <A> or --browser <B>) → Debugger is not attached to the tab with id: N.
  5. Disable/disconnect profile B's extension (leave profile A connected, browser process untouched) → step 2 still fails on profile A.
  6. Restart the browser → step 2 works again on profile A.

Daemon log of one such cycle (UTC, bsk logs):

13:32:34 INFO browser connected {"id": "…19c", "name": "chrome", "generation": 1}   # single instance → CDP OK
13:37:40 INFO browser connected {"id": "…bac", "name": "chrome", "generation": 2}   # second instance → CDP broken from here
13:46:04 INFO browser disconnected {"id": "…19c"}                                    # browser restart
13:46:04 INFO browser disconnected {"id": "…bac"}
13:49:15 INFO browser connected {"id": "…19c", "name": "chrome", "generation": 7}   # single instance → CDP OK again
13:49:46 INFO browser connected {"id": "…bac", "name": "chrome", "generation": 8}   # second instance → CDP broken again

What is ruled out (with evidence)

  • Not host permissions / not about:blank-specific. Fails identically on the auto-created about:blank Agent Window tab and on a user tab with a real https: URL borrowed via bsk tab borrow (borrow/return itself works — the tab is moved into the Agent Window and returned to its original window and index).
  • Not a permission grant. Secure Preferences for both profiles: granted_permissions.api includes debugger, explicit_host: ["<all_urls>"], disable_reasons: [], site access set to "on all sites".
  • Not the daemon. bsk daemon restart (fresh pid) changes nothing; doctor reports daemon running, daemon local process identity, protocol compatible all ok.
  • Not extension staleness. Reloading the extension on chrome://extensions (reload icon on the card) in either profile changes nothing.
  • Not version skew. daemon 0.3.0 / extension 0.3.0, both protocol 1.3.

Code-path note (why the error text points at a detach)

In the extension bundle the message can only come from chrome.debugger.sendCommand:

async ensureAttached(tabId) {
  …
  const r = (async () => {
    await this.api.attach({ tabId }, `1.3`);
    try { await this.enablePageDomain(tabId); …; this.attachedTabs.add(tabId) }
    catch (e) { await this.api.detach({ tabId }).catch(() => {}); throw e }  // rollback
  })().catch(e => { throw Kt(e) });                                          // attach failure → wrapped here
  …
}
async send(tabId, method, params) {
  this.attachedTabs.has(tabId) || await this.ensureAttached(tabId);
  return await this.api.sendCommand({ tabId }, method, params);              // ← our error comes from here
}

So the failing call is the first sendCommand after a "successful" attach (e.g. the Page.enable that navigate issues) — the browser reports the tab as no longer attached, or the attach was skipped because attachedTabs still claims the tab. With a second instance connected, that seems to happen on every new Agent Window tab.

Hypothesis (not proven)

Both extension instances share one extension id inside one browser process (Yandex's multi-profile model). If Chromium's debugger/permission bookkeeping for the debugger API is keyed per extension id rather than per profile, the two instances would collide and invalidate each other's devtools sessions — which would match the sticky behaviour and the "only a browser restart clears it" observation.

Impact

Keeping the extension in more than one profile (different logins: agency / personal) is the natural multi-profile use case of this tool, and it makes the tool unusable in all profiles until the browser is restarted. A documented single-profile recommendation (or a fix) would help.

Possibly separate, lower priority

After a full browser restart the unpacked extension came back disabled in Default (Secure Preferences: disable_reasons=[1], i.e. DISABLE_USER_ACTION), so bsk doctor reported 0 browsers connected until it was re-enabled on the card. If this reproduces on Chrome too, it is worth a line in AGENT_INSTALL.md (start the daemon, load the extension, and verify it is enabled before bsk doctor).

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the extension bundle's ensureAttached and send paths, especially the chrome.debugger.attach and sendCommand calls described in the issue. Reproduce the two-profile cycle, compare bsk logs before and after the second connection, and verify whether the shared extension ID invalidates sessions; done means a fix or a documented single-profile limitation, with AGENT_INSTALL.md updated if the installation note is confirmed.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.