RightNow-AI/openfang · error · BrowserResponse
Click failed: {e}
Error message
Click failed: {e} What it means
This is the CDP-transport-level click failure: the run_js call inside cmd_click returned Err, meaning the script never executed — the CDP connection itself failed rather than the click logic reporting failure. The inner CDP error is interpolated into the message.
Source
Thrown at crates/openfang-runtime/src/browser.rs:479
.and_then(|s| serde_json::from_str(s).ok())
.unwrap_or(val);
if parsed["success"].as_bool() == Some(false) {
return BrowserResponse::err(
parsed["error"]
.as_str()
.unwrap_or("Click failed")
.to_string(),
);
}
// Wait briefly for any navigation triggered by click
tokio::time::sleep(Duration::from_millis(500)).await;
self.wait_for_load().await;
match self.page_info().await {
Ok(info) => BrowserResponse::ok(info),
Err(_) => BrowserResponse::ok(parsed),
}
}
Err(e) => BrowserResponse::err(format!("Click failed: {e}")),
}
}
async fn cmd_type(&self, selector: &str, text: &str) -> BrowserResponse {
let sel_json = serde_json::to_string(selector).unwrap_or_default();
let text_json = serde_json::to_string(text).unwrap_or_default();
let js = format!(
r#"(() => {{
let sel = {sel_json};
let txt = {text_json};
let el = document.querySelector(sel);
if (!el) return JSON.stringify({{success: false, error: 'Input not found: ' + sel}});
el.focus();
el.value = txt;
el.dispatchEvent(new Event('input', {{bubbles: true}}));
el.dispatchEvent(new Event('change', {{bubbles: true}}));
return JSON.stringify({{success: true, selector: sel, typed: txt.length + ' chars'}});
}})()"#View on GitHub (pinned to acf2587e46)
Solutions
- Read the interpolated {e} for the underlying cause (disconnected, context destroyed, timeout).
- Reconnect or restart the browser session and retry the click.
- Re-navigate if the execution context was destroyed by an in-flight navigation.
- Wrap click in retry logic with a small backoff for transient CDP drops.
Example fix
// before
let resp = browser.execute("click", selector).await?;
// after
let resp = match browser.execute("click", selector).await {
Ok(r) if r.success => r,
Ok(r) => return Err(anyhow!(r.error)),
Err(e) => {
browser.reconnect().await?;
browser.execute("click", selector).await?
}
}; Defensive patterns
Strategy: retry
Validate before calling
// Check session liveness before clicking:
if !browser.is_connected().await { browser.reconnect().await?; } Type guard
fn is_cdp_transport_err(e: &anyhow::Error) -> bool {
let s = e.to_string();
s.contains("connection") || s.contains("closed") || s.contains("context")
} Try / catch
// Rust
match browser.execute("click", selector).await {
Ok(r) if r.success => Ok(r),
Ok(r) => Err(anyhow!(r.error)),
Err(e) if is_cdp_transport_err(&e) => {
browser.reconnect().await?;
browser.execute("click", selector).await.map_err(Into::into)
}
Err(e) => Err(e.into()),
} Prevention
- Serialize browser commands; never click while a navigation is in flight.
- Supervise the headless browser process and reconnect on death.
- Set explicit CDP evaluation timeouts and retry on timeout.
- Log the interpolated inner error to distinguish transport vs selector failures.
When it happens
Trigger: self.cdp.run_js(click_script) resolves to Err: browser disconnected, target/context closed, evaluation timed out, or the CDP session died between navigate and click.
Common situations: Headless Chrome crashed or was killed between commands; navigation destroyed the execution context while the click JS was being evaluated; CDP websocket dropped.
Related errors
- Type failed: {e}
- Navigate failed: {e}
- Navigate succeeded but page info failed: {e}
- Screenshot failed: {e}
- ReadPage failed: {e}
AI-assisted analysis of RightNow-AI/openfang@acf2587e46 (2026-09-02).
Data as JSON: /api/errors/641f24f7c39ce927.
Report an issue: GitHub.