{"record":{"id":"edacc26e4f9be470","repo":"BigPizzaV3/CodexPlusPlus","slug":"page-capturescreenshot-returned-invalid-png-data","errorCode":null,"errorMessage":"Page.captureScreenshot returned invalid PNG data","messagePattern":"Page\\.captureScreenshot returned invalid PNG data","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/bridge.rs","lineNumber":135,"sourceCode":"    output_path: &Path,\n) -> anyhow::Result<u64> {\n    let response = send_cdp_command(\n        websocket_url,\n        \"Page.captureScreenshot\",\n        capture_screenshot_params(),\n    )\n    .await?;\n    let encoded = response\n        .get(\"result\")\n        .and_then(|result| result.get(\"data\"))\n        .and_then(Value::as_str)\n        .filter(|data| !data.is_empty())\n        .ok_or_else(|| anyhow::anyhow!(\"Page.captureScreenshot returned no image data\"))?;\n    let bytes = base64::engine::general_purpose::STANDARD\n        .decode(encoded)\n        .context(\"failed to decode screenshot PNG\")?;\n    if !bytes.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10]) {\n        bail!(\"Page.captureScreenshot returned invalid PNG data\");\n    }\n    crate::settings::atomic_write(output_path, &bytes)\n        .with_context(|| format!(\"failed to save screenshot {}\", output_path.display()))?;\n    Ok(bytes.len() as u64)\n}\n\npub async fn run_periodic_evaluations<F>(\n    websocket_url: &str,\n    period: Duration,\n    mut next_expression: F,\n) -> anyhow::Result<()>\nwhere\n    F: FnMut() -> anyhow::Result<Option<String>>,\n{\n    let socket = connect_cdp_websocket(websocket_url).await?;\n    let mut session = CdpSession::new(socket);\n    let mut interval = tokio::time::interval(period);\n    loop {","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/fb3ebd9a82383aedd8d098aa9ae3aef9426d13a4/crates/codex-plus-core/src/bridge.rs#L117-L153","documentation":"capture_screenshot base64-decodes the data field of the CDP Page.captureScreenshot response and then validates the PNG magic signature (89 50 4E 47 0D 0A 1A 0A). This bail fires when decoding succeeded but the bytes are not a PNG: the endpoint returned some other payload - a different image format, an HTML/text error body, or garbage - under a success result.","triggerScenarios":"Page.captureScreenshot was invoked with a format other than png (jpeg/webp params) while validation still expects PNG magic; a non-standard Chromium/Electron build returning unusual data; a renderer crash producing a mangled payload.","commonSituations":"Screenshot params changed to jpeg/webp without updating the magic-byte check; Electron/Chromium version differences; capturing during a GPU process crash.","solutions":["Make sure the capture params request \"format\": \"png\" explicitly","Log the first bytes of the decoded payload to identify what was actually returned","Replay the same command via a raw CDP websocket or curl to inspect the raw base64","If another format is intended, branch the magic-byte check per requested format"],"exampleFix":"// before\nlet bytes = base64::engine::general_purpose::STANDARD.decode(encoded)?;\nif !bytes.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10]) {\n    bail!(\"Page.captureScreenshot returned invalid PNG data\");\n}\n\n// after - request PNG explicitly and diagnose on mismatch\nlet params = serde_json::json!({ \"format\": \"png\" });\nlet bytes = base64::engine::general_purpose::STANDARD\n    .decode(encoded).context(\"failed to decode screenshot data\")?;\nif !bytes.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10]) {\n    bail!(\n        \"Page.captureScreenshot returned invalid PNG data (first bytes: {:?})\",\n        bytes.get(..8).unwrap_or(&bytes)\n    );\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn looks_like_png(bytes: &[u8]) -> bool {\n    bytes.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10])\n}","tryCatchPattern":"let size = match capture_screenshot(&ws_url, &params, &out).await {\n    Ok(n) => n,\n    Err(e) if e.to_string().contains(\"invalid PNG data\") => {\n        tracing::warn!(\"screenshot format unexpected: {e:#}; skipping capture\");\n        return Ok(0);\n    }\n    Err(e) => return Err(e),\n};","preventionTips":["Always pass an explicit format in Page.captureScreenshot params","Do not assume payload formats survive Chromium/Electron version changes - validate magic bytes","Treat screenshot capture as best-effort: log and continue on format errors"],"tags":["cdp","screenshot","png","base64","chromium"],"backgroundTag":"invalid-image-data","analyzedSha":"fb3ebd9a82383aedd8d098aa9ae3aef9426d13a4","analyzedAt":"2026-08-17T11:35:12.031Z","contentChangedAt":"2026-08-17T11:35:12.031Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}