zeroclaw-labs/zeroclaw · error · anyhow::Error

computer-use sidecar returned an empty screenshot payload

Error message

computer-use sidecar returned an empty screenshot payload

What it means

For a path-bearing computer-use screenshot, ZeroClaw calls the sidecar, decodes data.png_base64, and requires a non-empty decoded buffer before writing locally. The flow is fail-closed: success must mean the file was actually created, so an empty payload aborts with this error instead of reporting success without a file.

Source

Thrown at crates/zeroclaw-tools/src/browser.rs:1167

                        .as_ref()
                        .and_then(|d| d.get("png_base64"))
                        .and_then(|v| v.as_str())
                        .ok_or_else(|| {
                            anyhow::Error::msg(crate::i18n::get_required_tool_string(
                                "tool-browser-screenshot-error-sidecar-no-png-data",
                            ))
                        })?;

                    // Decode and validate the PNG payload: it must decode to a
                    // non-empty buffer with a PNG signature. Base64-decodable
                    // arbitrary bytes are NOT a valid screenshot — writing them
                    // to the `.png` destination would turn the sidecar boundary
                    // into an arbitrary decoded-byte write.
                    let png_bytes = base64::engine::general_purpose::STANDARD
                        .decode(png_data)
                        .with_context(|| "Failed to decode PNG base64 data")?;
                    if png_bytes.is_empty() {
                        anyhow::bail!(crate::i18n::get_required_tool_string(
                            "tool-browser-screenshot-error-sidecar-empty-png",
                        ));
                    }
                    const PNG_SIGNATURE: &[u8] =
                        &[0x89, b'P', b'N', b'G', b'\r', b'\n', 0x1a, b'\n'];
                    if !png_bytes.starts_with(PNG_SIGNATURE) {
                        anyhow::bail!(crate::i18n::get_required_tool_string(
                            "tool-browser-screenshot-error-sidecar-not-png",
                        ));
                    }

                    tokio::fs::write(path_str, &png_bytes)
                        .await
                        .with_context(|| format!("Failed to write screenshot to {path_str}"))?;

                    // Return success with the path information
                    let output = serde_json::to_string_pretty(&json!({
                        "backend": "computer_use",

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Check the sidecar's own logs for why the capture produced zero bytes
  2. Verify the sidecar version and response contract (ComputerUseResponse with data.png_base64) and upgrade the mismatched side
  3. Retry once — transient capture races can produce empty frames; if it persists, report it as a sidecar bug
Defensive patterns

Strategy: try-catch

Try / catch

match tool.execute(args).await {
    Ok(res) if res.success => { /* file written */ }
    Ok(res) => {
        if res.error.as_deref().unwrap_or_default().contains("empty screenshot payload") {
            // sidecar contract violation: retry once, then report to the sidecar owner
        }
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: The sidecar replies 2xx with success=true but png_base64="" (or content that decodes to zero bytes) for a screenshot request that carries a destination path.

Common situations: Sidecar bug or version mismatch returning a canned/empty payload; screen capture failing silently in headless sessions with no visible window; sidecar stubs in tests returning shape-valid but empty responses.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/1fbf494cd34ec7aa. Report an issue: GitHub.