RightNow-AI/openfang · error · BrowserResponse
Navigate failed: {e}
Error message
Navigate failed: {e} What it means
cmd_navigate in openfang-runtime's browser module drives a headless browser over the Chrome DevTools Protocol (CDP). It sends a "Page.navigate" command with the target URL; if the CDP transport returns an Err (browser not running, connection dropped, IPC/WS failure, or navigation rejected), the error is wrapped into this message and returned as an error BrowserResponse instead of panicking.
Source
Thrown at crates/openfang-runtime/src/browser.rs:425
BrowserCommand::Wait {
selector,
timeout_ms,
} => self.cmd_wait(&selector, timeout_ms).await,
BrowserCommand::RunJs { expression } => self.cmd_run_js(&expression).await,
BrowserCommand::Back => self.cmd_back().await,
}
}
// ── Command implementations ────────────────────────────────────────
async fn cmd_navigate(&self, url: &str) -> BrowserResponse {
let result = self
.cdp
.send("Page.navigate", serde_json::json!({ "url": url }))
.await;
if let Err(e) = result {
return BrowserResponse::err(format!("Navigate failed: {e}"));
}
// Wait for page load
self.wait_for_load().await;
match self.page_info().await {
Ok(info) => BrowserResponse::ok(info),
Err(e) => BrowserResponse::err(format!("Navigate succeeded but page info failed: {e}")),
}
}
async fn cmd_click(&self, selector: &str) -> BrowserResponse {
let sel_json = serde_json::to_string(selector).unwrap_or_default();
let js = format!(
r#"(() => {{
let sel = {sel_json};
let el = document.querySelector(sel);
if (!el) {{View on GitHub (pinned to acf2587e46)
Solutions
- Check the browser/CDP process is running and reconnect (reinitialize the browser session) before retrying.
- Verify the URL is absolute and well-formed (include https:// scheme).
- Inspect the inner CDP error text in the message for transport diagnostics (e.g. connection refused).
- Add retry-with-backoff around navigate for transient connection drops.
Example fix
// before
let result = self.cdp.send("Page.navigate", serde_json::json!({ "url": url })).await;
// after
if !url.starts_with("http://") && !url.starts_with("https://") {
return BrowserResponse::err(format!("Invalid URL: {url}"));
}
let result = self.cdp.send("Page.navigate", serde_json::json!({ "url": url })).await; Defensive patterns
Strategy: retry
Validate before calling
// Rust
fn is_navigable(url: &str) -> bool {
url.starts_with("http://") || url.starts_with("https://")
}
if !is_navigable(url) { return Err(anyhow!("invalid url: {url}")); } Type guard
fn is_transport_err(resp: &BrowserResponse) -> bool {
!resp.success && resp.error.contains("connection") || !resp.success && resp.error.contains("closed")
} Try / catch
// Rust
match browser.execute("navigate", url).await {
Ok(r) if r.success => Ok(r),
Ok(r) => Err(anyhow!(r.error)),
Err(e) if e.to_string().contains("connection") => {
browser.reconnect().await?;
browser.execute("navigate", url).await.map_err(Into::into)
}
Err(e) => Err(e.into()),
} Prevention
- Health-check the CDP connection before each navigation batch.
- Always pass absolute URLs with an explicit scheme.
- Keep the headless browser process supervised so crashes are detected early.
- Retry transient transport errors with exponential backoff.
When it happens
Trigger: Calling navigate (via the runtime execute dispatch) when the CDP connection in self.cdp cannot deliver the "Page.navigate" command: browser process died, connection never established, or the CDP send future resolves to Err.
Common situations: Chrome/Chromium was closed or crashed between commands; the runtime was constructed without a live browser session; invalid URL scheme the browser refuses; resource exhaustion killing the headless process.
Related errors
- Screenshot failed: {e}
- ReadPage failed: {e}
- Scroll failed: {e}
- Back succeeded but page info failed: {e}
- Back failed: {e}
AI-assisted analysis of RightNow-AI/openfang@acf2587e46 (2026-09-02).
Data as JSON: /api/errors/346c4a2cb6455b3b.
Report an issue: GitHub.