{"record":{"id":"1b4a08e132a71895","repo":"RightNow-AI/openfang","slug":"js-execution-failed-e","errorCode":null,"errorMessage":"JS execution failed: {e}","messagePattern":"JS execution failed: (.+?)","errorType":"error_code","errorClass":"BrowserResponse","httpStatus":null,"severity":"error","filePath":"crates/openfang-runtime/src/browser.rs","lineNumber":601,"sourceCode":"            if let Ok(val) = self.cdp.run_js(&js).await {\n                if val.as_str() == Some(\"found\") {\n                    return BrowserResponse::ok(\n                        serde_json::json!({\"found\": true, \"selector\": selector}),\n                    );\n                }\n            }\n            tokio::time::sleep(Duration::from_millis(PAGE_LOAD_POLL_INTERVAL_MS)).await;\n        }\n\n        BrowserResponse::err(format!(\n            \"Timed out waiting for selector: {selector} ({max_ms}ms)\"\n        ))\n    }\n\n    async fn cmd_run_js(&self, expression: &str) -> BrowserResponse {\n        match self.cdp.run_js(expression).await {\n            Ok(val) => BrowserResponse::ok(serde_json::json!({\"result\": val})),\n            Err(e) => BrowserResponse::err(format!(\"JS execution failed: {e}\")),\n        }\n    }\n\n    async fn cmd_back(&self) -> BrowserResponse {\n        match self.cdp.run_js(\"history.back(); 'ok'\").await {\n            Ok(_) => {\n                tokio::time::sleep(Duration::from_millis(500)).await;\n                self.wait_for_load().await;\n                match self.page_info().await {\n                    Ok(info) => BrowserResponse::ok(info),\n                    Err(e) => {\n                        BrowserResponse::err(format!(\"Back succeeded but page info failed: {e}\"))\n                    }\n                }\n            }\n            Err(e) => BrowserResponse::err(format!(\"Back failed: {e}\")),\n        }\n    }","sourceCodeStart":583,"sourceCodeEnd":619,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-runtime/src/browser.rs#L583-L619","documentation":"cmd_run_js forwards the expression to the CDP connection (self.cdp.run_js) and wraps any Err into this error string. The library throws it whenever Runtime.evaluate fails at the transport or protocol level — connection loss, evaluation exception returned as an error, or an invalid execution context — not when the JS merely returns an unexpected value (that path returns Ok).","triggerScenarios":"Calling the run_js command when the CDP WebSocket to the browser is closed or dropped, the target execution context was destroyed (page navigated or crashed mid-call), the expression has a syntax error that Chrome rejects at evaluation, or the browser process died.","commonSituations":"Evaluating JS right after clicking a link that navigates (context destroyed); a headless Chrome crash under memory pressure; sending multi-statement scripts where only expressions are safe; the automation session outliving the browser (timeout on the underlying tab).","solutions":["Confirm the browser/CDP session is alive (retry navigation or reconnect) before re-running the script.","Check the embedded error {e} — 'SyntaxError' means fix the expression; 'Execution context was destroyed' means wait for navigation to settle first.","Run document.readyState polling (wait_for_load equivalent) or a small no-op JS after navigation before evaluating real code.","Wrap the logic in try/catch inside the JS itself so page exceptions surface as return values, not evaluation errors.","If the script depends on page state, guard with a feature check (typeof foo !== 'undefined')."],"exampleFix":"// before: evaluate immediately after navigation\nbrowser.cmd_run_js(\"window.app.getState()\");\n// after: wait for context, then evaluate defensively\nbrowser.wait_for_load().await;\nbrowser.cmd_run_js(\"(typeof window.app !== 'undefined') ? JSON.stringify(window.app.getState()) : 'null'\");","handlingStrategy":"try-catch","validationCode":"let alive = browser.cmd_run_js(\"1+1\");\nif alive.is_err() { /* CDP session is dead — reconnect or relaunch before real work */ }","typeGuard":"fn is_eval_error(resp: &BrowserResponse) -> bool {\n    resp.error.as_deref().map(|e| e.starts_with(\"JS execution failed\")).unwrap_or(false)\n}\nfn is_context_destroyed(resp: &BrowserResponse) -> bool {\n    resp.error.as_deref().map(|e| e.contains(\"context was destroyed\")).unwrap_or(false)\n}","tryCatchPattern":"match browser.cmd_run_js(expr) {\n    Ok(r) => r,\n    Err(e) if e.contains(\"context was destroyed\") => { wait_for_load(); browser.cmd_run_js(expr) }\n    Err(e) if e.contains(\"SyntaxError\") => return Err(format!(\"bad script: {e}\")),\n    Err(e) => Err(e),\n}","preventionTips":["Probe the session with a trivial expression before running important scripts.","Wrap page logic in an in-JS try/catch and return errors as values instead of throwing.","Never evaluate immediately after navigation — poll document.readyState first.","Keep scripts as single expressions (Runtime.evaluate semantics); avoid bare multi-statement code.","Reconnect CDP sessions proactively in long-running automation instead of assuming liveness."],"tags":["browser","javascript","cdp","evaluation"],"backgroundTag":"js-evaluation-failed","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}