BigPizzaV3/CodexPlusPlus · error · anyhow::Error
Page.captureScreenshot returned invalid PNG data
Error message
Page.captureScreenshot returned invalid PNG data
What it means
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.
Source
Thrown at crates/codex-plus-core/src/bridge.rs:135
output_path: &Path,
) -> anyhow::Result<u64> {
let response = send_cdp_command(
websocket_url,
"Page.captureScreenshot",
capture_screenshot_params(),
)
.await?;
let encoded = response
.get("result")
.and_then(|result| result.get("data"))
.and_then(Value::as_str)
.filter(|data| !data.is_empty())
.ok_or_else(|| anyhow::anyhow!("Page.captureScreenshot returned no image data"))?;
let bytes = base64::engine::general_purpose::STANDARD
.decode(encoded)
.context("failed to decode screenshot PNG")?;
if !bytes.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10]) {
bail!("Page.captureScreenshot returned invalid PNG data");
}
crate::settings::atomic_write(output_path, &bytes)
.with_context(|| format!("failed to save screenshot {}", output_path.display()))?;
Ok(bytes.len() as u64)
}
pub async fn run_periodic_evaluations<F>(
websocket_url: &str,
period: Duration,
mut next_expression: F,
) -> anyhow::Result<()>
where
F: FnMut() -> anyhow::Result<Option<String>>,
{
let socket = connect_cdp_websocket(websocket_url).await?;
let mut session = CdpSession::new(socket);
let mut interval = tokio::time::interval(period);
loop {View on GitHub (pinned to fb3ebd9a82)
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
Example fix
// before
let bytes = base64::engine::general_purpose::STANDARD.decode(encoded)?;
if !bytes.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10]) {
bail!("Page.captureScreenshot returned invalid PNG data");
}
// after - request PNG explicitly and diagnose on mismatch
let params = serde_json::json!({ "format": "png" });
let bytes = base64::engine::general_purpose::STANDARD
.decode(encoded).context("failed to decode screenshot data")?;
if !bytes.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10]) {
bail!(
"Page.captureScreenshot returned invalid PNG data (first bytes: {:?})",
bytes.get(..8).unwrap_or(&bytes)
);
} Defensive patterns
Strategy: try-catch
Type guard
fn looks_like_png(bytes: &[u8]) -> bool {
bytes.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10])
} Try / catch
let size = match capture_screenshot(&ws_url, ¶ms, &out).await {
Ok(n) => n,
Err(e) if e.to_string().contains("invalid PNG data") => {
tracing::warn!("screenshot format unexpected: {e:#}; skipping capture");
return Ok(0);
}
Err(e) => return Err(e),
}; Prevention
- 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
When it happens
Trigger: 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.
Common situations: Screenshot params changed to jpeg/webp without updating the magic-byte check; Electron/Chromium version differences; capturing during a GPU process crash.
Related errors
- periodic Runtime.evaluate reported unavailable capability
- CDP WebSocket port {port} does not match debug port {expecte
- No injectable page target found
- No injectable Codex page target found
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@fb3ebd9a82 (2026-08-17).
Data as JSON: /api/errors/edacc26e4f9be470.
Report an issue: GitHub.