RightNow-AI/openfang · error · BrowserResponse
Screenshot failed: {e}
Error message
Screenshot failed: {e} What it means
This error fires when the CDP command "Page.captureScreenshot" fails during cmd_screenshot, meaning the headless browser could not capture a PNG of the current page. The CDP send returns an Err when the browser target is unavailable or has crashed, the page or tab was closed or navigated mid-request, DevTools protocol communication broke, or the browser refused the screenshot request; the underlying CDP error is embedded in the message. It indicates the screenshot operation itself failed at the protocol level, not that the resulting image data was empty or malformed (a missing "data" field would silently yield an empty base64 string instead).
Source
Thrown at crates/openfang-runtime/src/browser.rs:538
"Page.captureScreenshot",
serde_json::json!({ "format": "png" }),
)
.await
{
Ok(result) => {
let b64 = result["data"].as_str().unwrap_or("");
let url = self
.cdp
.run_js("location.href")
.await
.ok()
.and_then(|v| v.as_str().map(String::from))
.unwrap_or_default();
BrowserResponse::ok(
serde_json::json!({"image_base64": b64, "url": url, "format": "png"}),
)
}
Err(e) => BrowserResponse::err(format!("Screenshot failed: {e}")),
}
}
async fn cmd_read_page(&self) -> BrowserResponse {
match self.cdp.run_js(EXTRACT_CONTENT_JS).await {
Ok(val) => {
let parsed: serde_json::Value = val
.as_str()
.and_then(|s| serde_json::from_str(s).ok())
.unwrap_or(val);
BrowserResponse::ok(parsed)
}
Err(e) => BrowserResponse::err(format!("ReadPage failed: {e}")),
}
}
async fn cmd_scroll(&self, direction: &str, amount: i32) -> BrowserResponse {
let (dx, dy) = match direction {View on GitHub (pinned to acf2587e46)
Solutions
- Read the interpolated {e} for the CDP-level cause.
- Retry the screenshot after wait_for_load completes — avoid capturing mid-navigation.
- Reconnect/restart the browser session if the connection dropped.
- Reduce viewport size or use format options if the capture times out on huge pages.
Example fix
// before
let shot = browser.execute("screenshot", "").await?;
// after
browser.wait_for_load().await?;
let shot = match browser.execute("screenshot", "").await {
Ok(s) => s,
Err(_) => {
tokio::time::sleep(std::time::Duration::from_millis(300)).await;
browser.execute("screenshot", "").await?
}
}; Defensive patterns
Strategy: retry
Validate before calling
// Only screenshot a settled page:
browser.wait_for_load().await?;
if !browser.is_connected().await { browser.reconnect().await?; } Type guard
fn screenshot_payload_valid(resp: &BrowserResponse) -> bool {
resp.success && resp.value.get("image_base64").and_then(|v| v.as_str()).map_or(false, |s| !s.is_empty())
} Try / catch
// Rust
let shot = match browser.execute("screenshot", "").await {
Ok(s) if s.success => Ok(s),
Ok(s) => Err(anyhow!(s.error)),
Err(_) => {
tokio::time::sleep(Duration::from_millis(300)).await;
browser.execute("screenshot", "").await.map_err(Into::into)
}
}; Prevention
- Never screenshot during navigation; wait for load first.
- Keep the viewport at a sane size to avoid capture timeouts.
- Verify the base64 payload decodes before persisting it.
- Retry once on transport errors before failing the workflow.
When it happens
Trigger: self.cdp Page.captureScreenshot (via run/send) resolves to Err: browser disconnected, target crashed, or CDP rejected the capture (e.g. unsupported surface, tab closing).
Common situations: Capturing during a navigation or while the tab is being closed; headless Chrome crashed; very large viewport causing the capture to fail/timeout.
Related errors
- Navigate failed: {e}
- ReadPage failed: {e}
- Scroll failed: {e}
- Navigate succeeded but page info failed: {e}
- Click failed
AI-assisted analysis of RightNow-AI/openfang@acf2587e46 (2026-09-02).
Data as JSON: /api/errors/5ad6f873e4ce8fdf.
Report an issue: GitHub.