Problem
After opencli browser open followed by a full-page navigation (not a modal overlay), all subsequent CDP commands fail with No window with id.
Working cases (modal overlay URLs — no CDP target reset):
post → x.com/compose/tweet ✅
reply → x.com/compose/post?in_reply_to=... ✅
Broken cases (full-page navigation — triggers CDP target recreate):
follow → x.com/{username} ❌
like → x.com/status/... ❌
search → x.com/explore → SPA navigation ❌
timeline → page.evaluate on current page ❌
Root Cause
In src/browser/page.js, the goto() method:
- Calls
sendCommandFull('navigate', { url, ...this._cmdOpts() }) where this._cmdOpts() includes the stale this._page (the old/失效的 target ID)
- The navigate action destroys the old CDP target and creates a new one
- The new target's ID is returned in
result.page, and goto() correctly saves it: this._page = result.page
- BUT the subsequent
sendCommand('exec', ...) call at line ~45 uses the same this._cmdOpts() — which still contains the old page field from before the assignment
The sendCommand('exec', ...) is made inside the if (options?.waitUntil !== 'none') block before this._page = result.page takes effect for that call, because this._cmdOpts() is evaluated before the assignment.
Even when the exec call is retried after a settle error, it still uses the old this._page.
Impact
PR #892 (retry on No window with id CDP error) was merged but did not fully fix this — it addressed the retry classification layer but not the root cause: this._page becoming stale after a full-page navigation that triggers a CDP target recreate.
Suggested Fix
The sendCommand('exec', ...) call after navigate should use the new page identity, not the old one. Options:
- Inline the new page ID into the exec call — pass
page: result.page directly instead of relying on this._cmdOpts()
- Re-bind after navigate — call
selectTab(0) or bindCurrentTab after navigate to ensure this._page is fresh
- Don't cache page identity in
goto() at all — always fetch the current active page fresh for each command (simplest, but may have performance implications)
Test Script
opencli browser open https://x.com
opencli twitter follow elonmusk # fails: No window with id
# vs
opencli browser open https://x.com/compose/tweet
opencli twitter post "test" # works: modal overlay, no target reset
Environment
- OpenCLI v1.7.0
- macOS
- Chrome Extension automation
Problem
After
opencli browser openfollowed by a full-page navigation (not a modal overlay), all subsequent CDP commands fail withNo window with id.Working cases (modal overlay URLs — no CDP target reset):
post→x.com/compose/tweet✅reply→x.com/compose/post?in_reply_to=...✅Broken cases (full-page navigation — triggers CDP target recreate):
follow→x.com/{username}❌like→x.com/status/...❌search→x.com/explore→ SPA navigation ❌timeline→ page.evaluate on current page ❌Root Cause
In
src/browser/page.js, thegoto()method:sendCommandFull('navigate', { url, ...this._cmdOpts() })wherethis._cmdOpts()includes the stalethis._page(the old/失效的 target ID)result.page, andgoto()correctly saves it:this._page = result.pagesendCommand('exec', ...)call at line ~45 uses the samethis._cmdOpts()— which still contains the oldpagefield from before the assignmentThe
sendCommand('exec', ...)is made inside theif (options?.waitUntil !== 'none')block beforethis._page = result.pagetakes effect for that call, becausethis._cmdOpts()is evaluated before the assignment.Even when the exec call is retried after a settle error, it still uses the old
this._page.Impact
PR #892 (retry on
No window with idCDP error) was merged but did not fully fix this — it addressed the retry classification layer but not the root cause:this._pagebecoming stale after a full-page navigation that triggers a CDP target recreate.Suggested Fix
The
sendCommand('exec', ...)call after navigate should use the newpageidentity, not the old one. Options:page: result.pagedirectly instead of relying onthis._cmdOpts()selectTab(0)orbindCurrentTabafter navigate to ensurethis._pageis freshgoto()at all — always fetch the current active page fresh for each command (simplest, but may have performance implications)Test Script
Environment