BigPizzaV3/CodexPlusPlus · error · anyhow::Error

Runtime.evaluate raised an exception

Error message

Runtime.evaluate raised an exception: {exception}

What it means

ensure_runtime_evaluate_succeeded checks Runtime.evaluate responses for result.exceptionDetails and, if JavaScript execution threw, bails with the serialized exception details. It is used both by direct script evaluation (evaluate_script_with_await_promise) and by periodic probes, so any injected script error surfaces here with the full CDP exception object in the message.

Solutions

  1. Parse the exceptionDetails in the message — it contains exception description, line/column, and stack trace
  2. Run the script manually in the target's DevTools console to reproduce and fix the JS error
  3. Guard the script against missing globals (typeof checks) so it degrades instead of throwing
  4. Ensure evaluation happens on a live, fully-loaded document; re-inject via add_script_to_new_documents after updates

Example fix

// before
return window.__cap.doWork();
// after
if (typeof window.__cap === 'undefined') return null;
return window.__cap.doWork();
Defensive patterns

Strategy: try-catch

Validate before calling

// check the globals your script depends on exist before evaluating
let probe = evaluate_script(&ws, "return typeof window.__cap").await?;
if probe.as_str() != Some("object") { eprintln!("__cap not injected yet"); }

Type guard

fn has_exception_details(response: &serde_json::Value) -> bool {
    response.get("result").and_then(|r| r.get("exceptionDetails")).is_some()
}

Try / catch

match evaluate_script(&ws, script).await {
    Err(e) if e.to_string().contains("raised an exception") => {
        // exceptionDetails in the message has description + stack; fix the script and retry
        eprintln!("script threw: {e}");
    }
    other => other?,
}

Prevention

When it happens

Trigger: The evaluated JavaScript throws: referencing a undefined global (e.g. window.__codexPlusAppServerClientClass missing), a syntax error in the script, an unhandled promise rejection with awaitPromise:true, or the target context being destroyed mid-evaluation.

Common situations: App update removed/renamed the internal objects the injected script touches; typo or version mismatch in the injected script; evaluating before the page finished loading; awaitPromise rejecting on network-dependent code.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/bad60fb191971ad0. Report an issue: GitHub.

Appendix: source

Thrown at crates/codex-plus-core/src/bridge.rs:963

            }
        }
        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"))
        .and_then(|result| result.get("value"))
        .is_some_and(|value| value == false)
}

fn extract_string_field(input: &str, field: &str) -> Option<String> {
    let needle = format!("\"{field}\"");
    let mut index = input.find(&needle)? + needle.len();
    let bytes = input.as_bytes();

    while matches!(bytes.get(index), Some(b' ' | b'\n' | b'\r' | b'\t')) {

View on GitHub (pinned to b1ed92e5e4)