{"record":{"id":"bad60fb191971ad0","repo":"BigPizzaV3/CodexPlusPlus","slug":"runtime-evaluate-raised-an-exception-exception","errorCode":null,"errorMessage":"Runtime.evaluate raised an exception: {exception}","messagePattern":"Runtime\\.evaluate raised an exception: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/bridge.rs","lineNumber":963,"sourceCode":"            }\n        }\n        sent.map(|_| ())\n    }\n}\n\nfn command_result(response: Value, method: &str, message_id: u64) -> anyhow::Result<Value> {\n    if let Some(error) = response.get(\"error\") {\n        bail!(\"CDP command {method} id {message_id} failed: {error}\");\n    }\n    Ok(response)\n}\n\nfn ensure_runtime_evaluate_succeeded(response: Value) -> anyhow::Result<Value> {\n    if let Some(exception) = response\n        .get(\"result\")\n        .and_then(|result| result.get(\"exceptionDetails\"))\n    {\n        bail!(\"Runtime.evaluate raised an exception: {exception}\");\n    }\n    Ok(response)\n}\n\nfn runtime_evaluate_result_is_false(response: &Value) -> bool {\n    response\n        .get(\"result\")\n        .and_then(|result| result.get(\"result\"))\n        .and_then(|result| result.get(\"value\"))\n        .is_some_and(|value| value == false)\n}\n\nfn extract_string_field(input: &str, field: &str) -> Option<String> {\n    let needle = format!(\"\\\"{field}\\\"\");\n    let mut index = input.find(&needle)? + needle.len();\n    let bytes = input.as_bytes();\n\n    while matches!(bytes.get(index), Some(b' ' | b'\\n' | b'\\r' | b'\\t')) {","sourceCodeStart":945,"sourceCodeEnd":981,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/bridge.rs#L945-L981","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Parse the exceptionDetails in the message — it contains exception description, line/column, and stack trace","Run the script manually in the target's DevTools console to reproduce and fix the JS error","Guard the script against missing globals (typeof checks) so it degrades instead of throwing","Ensure evaluation happens on a live, fully-loaded document; re-inject via add_script_to_new_documents after updates"],"exampleFix":"// before\nreturn window.__cap.doWork();\n// after\nif (typeof window.__cap === 'undefined') return null;\nreturn window.__cap.doWork();","handlingStrategy":"try-catch","validationCode":"// check the globals your script depends on exist before evaluating\nlet probe = evaluate_script(&ws, \"return typeof window.__cap\").await?;\nif probe.as_str() != Some(\"object\") { eprintln!(\"__cap not injected yet\"); }","typeGuard":"fn has_exception_details(response: &serde_json::Value) -> bool {\n    response.get(\"result\").and_then(|r| r.get(\"exceptionDetails\")).is_some()\n}","tryCatchPattern":"match evaluate_script(&ws, script).await {\n    Err(e) if e.to_string().contains(\"raised an exception\") => {\n        // exceptionDetails in the message has description + stack; fix the script and retry\n        eprintln!(\"script threw: {e}\");\n    }\n    other => other?,\n}","preventionTips":["Use typeof guards in injected scripts so missing internals degrade to null instead of throwing","Test scripts in the target's DevTools console against the exact app version","Ensure the page is loaded and the execution context is live before Runtime.evaluate; re-inject on new documents"],"tags":["cdp","javascript","runtime-evaluate","exception"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}