{"record":{"id":"9e39ac9cf50b701b","repo":"RightNow-AI/openfang","slug":"back-failed-e","errorCode":null,"errorMessage":"Back failed: {e}","messagePattern":"Back failed: (.+?)","errorType":"error_code","errorClass":"BrowserResponse","httpStatus":null,"severity":"error","filePath":"crates/openfang-runtime/src/browser.rs","lineNumber":617,"sourceCode":"        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    }\n\n    // ── Helpers ────────────────────────────────────────────────────────\n\n    /// Poll until document.readyState is 'complete' or 'interactive'.\n    async fn wait_for_load(&self) {\n        for _ in 0..PAGE_LOAD_MAX_POLLS {\n            if let Ok(val) = self.cdp.run_js(\"document.readyState\").await {\n                let state = val.as_str().unwrap_or(\"\");\n                if state == \"complete\" || state == \"interactive\" {\n                    return;\n                }\n            }\n            tokio::time::sleep(Duration::from_millis(PAGE_LOAD_POLL_INTERVAL_MS)).await;\n        }\n    }\n","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-runtime/src/browser.rs#L599-L635","documentation":"cmd_back first runs history.back() through CDP. If that evaluation itself returns Err — before any navigation is even attempted successfully — the library short-circuits with this error. Unlike error 32, navigation did NOT happen; the failure is in issuing/executing the history.back() JS on the current page (connection or context problem), or the JS threw.","triggerScenarios":"CDP connection closed or browser tab crashed when cmd_back is called; the current execution context was destroyed by an in-flight navigation or page crash so Runtime.evaluate fails; the current page's script environment is unresponsive (blocked main thread), making the evaluation time out.","commonSituations":"Calling back on a page that just triggered its own navigation; long-running automation where the Chrome session died; pages with a hung synchronous script freezing the main thread; browser closed by an earlier timeout while the tool session persists.","solutions":["Check the browser/CDP session health and reconnect or relaunch the browser if the connection is gone.","Inspect the embedded {e}: 'Execution context was destroyed' → wait for the pending navigation to finish, then retry back.","If the main thread is blocked by page script, force navigation via CDP Page.navigateTo (history entry) instead of history.back().","Retry cmd_back after wait_for_load-style polling shows an evaluable readyState.","Verify the history stack actually has a previous entry (history.length > 1) to rule out a no-op followed by a context error."],"exampleFix":"// before: unconditional back\nbrowser.cmd_back();\n// after: ensure evaluable page, retry once\nif browser.cmd_back().is_err() {\n    browser.wait_for_load().await;\n    browser.cmd_back().or_else(|_| browser.cmd_run_js(\"location.href = document.referrer\"));\n}","handlingStrategy":"retry","validationCode":"let probe = browser.cmd_run_js(\"history.length\");\nif probe.is_err() || probe.result.as_i64().unwrap_or(1) < 2 { /* no history to go back to, or session is dead */ }","typeGuard":"fn is_back_failure(resp: &BrowserResponse) -> bool {\n    resp.error.as_deref().map(|e| e.starts_with(\"Back failed:\")).unwrap_or(false)\n}","tryCatchPattern":"match browser.cmd_back() {\n    Ok(r) => r,\n    Err(e) => {\n        if !session_alive(browser) { reconnect_browser()?; }\n        wait_for_load();\n        browser.cmd_back().map_err(|e2| format!(\"back retry failed: {e} / {e2}\"))\n    }\n}","preventionTips":["Health-check the CDP session (cheap run_js) before navigation commands.","Check history.length > 1 before issuing back so dead sessions and empty stacks are distinguished.","After any in-page navigation, wait for readyState before issuing back.","Detect hung pages (blocked main thread) and fall back to direct URL navigation via CDP.","In long-running automation, monitor browser process liveness and relaunch on death."],"tags":["browser","navigation","cdp","history"],"backgroundTag":"cdp-connection-lost","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}