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

  1. Check the browser/CDP process is running and reconnect (reinitialize the browser session) before retrying.
  2. Verify the URL is absolute and well-formed (include https:// scheme).
  3. Inspect the inner CDP error text in the message for transport diagnostics (e.g. connection refused).
  4. 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

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


AI-assisted analysis of RightNow-AI/openfang@acf2587e46 (2026-09-02). Data as JSON: /api/errors/346c4a2cb6455b3b. Report an issue: GitHub.