agent-browser back (and, by the same code, forward) can return an error even though the navigation succeeded:
$ agent-browser --json back
{"success":false,"error":"CDP error (Runtime.evaluate): Inspected target navigated or closed"}
$ agent-browser get url
http://localhost:8931/ # the previous page — the back navigation happenedIt is intermittent. On macOS with Chrome for Testing it failed 3 of 3 times against pages served by python3 -m http.server, and only sometimes against a small Node http server.
Reproduce
mkdir /tmp/ab-back && cd /tmp/ab-back
echo '<a href="two.html">two</a>' > index.html
echo '<p>two</p>' > two.html
python3 -m http.server 8931 &
agent-browser open http://localhost:8931/
agent-browser open http://localhost:8931/two.html
agent-browser --json back # often: success:false, "Inspected target navigated or closed"
agent-browser get url # http://localhost:8931/Seen on agent-browser 0.39.1; the code path is unchanged on main (dac13bb).
Cause
handle_back in cli/src/native/actions.rs (~L6826 on main) runs
mgr.evaluate("history.back()", None).await?;
tokio::time::sleep(Duration::from_millis(500)).await;
let url = mgr.get_url().await.unwrap_or_default();and waits for the Runtime.evaluate reply. The navigation history.back() starts tears down the execution context, so the reply can arrive as "Inspected target navigated or closed". The ? propagates it, and the sleep/get_url that would report the new page never run. handle_forward (~L6845) is identical. The race is plausibly lost more often when the previous page is restored from the back/forward cache, but that is a guess.
Suggested fix
Either of:
- Navigate through CDP history instead of page script:
Page.getNavigationHistory, thenPage.navigateToHistoryEntrywith the previous/next entry id. That does not depend on the page's execution context surviving. - Or treat "Inspected target navigated or closed" from this specific
evaluateas success and continue to the existing wait andget_url.
Environment
- agent-browser 0.39.1 (native CLI), Chrome for Testing, macOS
- Pages served by
python3 -m http.server(fails consistently) and a Nodehttpserver (fails sometimes)
Activity
3Confirmed the root cause: in cli/src/native/actions.rs on main, both handle_back (~L6826) and handle_forward (~L6845) do mgr.evaluate("history.back()", None).await? / mgr.evaluate("history.forward()", None).await? — the ? propagates the Inspected target navigated or closed CDP error that arrives when the navigation started by the script tears down the execution context, so the following sleep + get_url (which would report the new URL) never run even though the navigation succeeded.
I'm working on a fix (treat that specific error from this evaluate call as success and continue to the existing wait + URL read, keeping the change scoped to these two call sites). Will open a PR shortly — happy to consider the Page.getNavigationHistory/navigateToHistoryEntry approach if maintainers prefer it.
NOTE
This comment and the upcoming PR are authored with AI assistance (Claude, an AI coding agent), under human review.
The fix is up as #2129. It goes with the Page.getNavigationHistory/Page.navigateToHistoryEntry approach (browser-side, so the navigation can't destroy the execution context the command depends on), with a narrowed fallback to the page-script evaluation for engines without those commands. Full root cause, test evidence, and the three new mock-CDP regression tests are in the PR description.
Since the execution context is destroyed during history navigation, we should wrap the
mgr.evaluatecall in a try-catch block to ignore the "Inspected target navigated or closed" error, then rely solely on the subsequent URL check to confirm the operation succeeded.