BigPizzaV3/CodexPlusPlus · error · anyhow::Error
CDP command id failed
Error message
CDP command {method} id {message_id} failed: {error} What it means
command_result inspects a CDP response and, when it contains an "error" object, converts it into a Rust error embedding the method name, message id, and the serialized error payload. This is the standard surface for CDP-level protocol errors (unknown method, invalid parameters, internal browser errors) — the command was delivered and answered, but with a failure result.
Solutions
- Read the embedded error JSON in the message — CDP errors include code and message explaining the cause
- Ensure required domains are enabled first (e.g. Page.enable before Page commands)
- Align CDP method/params with the target browser's supported protocol version
- Re-issue the command after navigation/reload when the error references a destroyed context
Example fix
// before
session.send_command(id, "Page.captureScreenshot", params).await?;
// after
session.send_command(id, "Page.enable", json!({})).await?;
session.send_command(id, "Page.captureScreenshot", params).await?; Defensive patterns
Strategy: try-catch
Validate before calling
// check domain support before calling (protocol version sniff)
let version = send_cdp_command(&ws, "Browser.getVersion", json!({})).await?;
eprintln!("target: {}", version["result"]["product"]); Type guard
fn is_cdp_error(response: &serde_json::Value) -> bool {
response.get("error").is_some()
} Try / catch
match session.send_command(id, method, params).await {
Err(e) if e.to_string().contains("failed:") => {
// e contains the CDP error object; log method+id and adjust params or enable the domain
eprintln!("CDP error on {method}: {e}");
}
other => other?,
} Prevention
- Enable required domains (Page.enable, Runtime.enable) before their commands
- Keep method/params in sync with the target browser's protocol version
- Re-issue context-dependent commands after navigation (stale execution contexts are a common cause)
When it happens
Trigger: Any send_command whose response carries an "error" field: calling an unsupported CDP method on the browser version, invalid params, or browser-side errors (e.g. 'Runtime.evaluate' on a destroyed execution context, Page domain not enabled).
Common situations: Version drift between the bridge and the target Chromium dropping/renaming CDP methods; sending Page commands before Page.enable; referencing a stale execution context after navigation; typos in method or parameter names.
Related errors
- CDP websocket closed before response for
- Page.captureScreenshot returned invalid PNG data
- browser WebSocket URL has no Browser ID
- browser WebSocket URL has no path
- CDP WebSocket host must be loopback
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/fa40223cbb842fef.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/bridge.rs:953
}
Err(error) => {
let _ = crate::diagnostic_log::append_diagnostic_log(
"bridge.reject_failed",
json!({
"request_id": request_id,
"message_id": message_id,
"error": error.to_string()
}),
);
}
}
sent.map(|_| ())
}
}
fn command_result(response: Value, method: &str, message_id: u64) -> anyhow::Result<Value> {
if let Some(error) = response.get("error") {
bail!("CDP command {method} id {message_id} failed: {error}");
}
Ok(response)
}
fn ensure_runtime_evaluate_succeeded(response: Value) -> anyhow::Result<Value> {
if let Some(exception) = response
.get("result")
.and_then(|result| result.get("exceptionDetails"))
{
bail!("Runtime.evaluate raised an exception: {exception}");
}
Ok(response)
}
fn runtime_evaluate_result_is_false(response: &Value) -> bool {
response
.get("result")
.and_then(|result| result.get("result"))View on GitHub (pinned to b1ed92e5e4)