{"record":{"id":"828ac4cbda328036","repo":"RightNow-AI/openfang","slug":"back-succeeded-but-page-info-failed-e","errorCode":null,"errorMessage":"Back succeeded but page info failed: {e}","messagePattern":"Back succeeded but page info failed: (.+?)","errorType":"error_code","errorClass":"BrowserResponse","httpStatus":null,"severity":"error","filePath":"crates/openfang-runtime/src/browser.rs","lineNumber":613,"sourceCode":"        ))\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    }\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            }","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-runtime/src/browser.rs#L595-L631","documentation":"cmd_back executes history.back() via CDP; if that succeeds, it sleeps 500ms, waits for load, then calls page_info() to fetch title/URL/content. If history.back() worked but the subsequent page_info() JS evaluation fails, the library reports this error. Navigation happened, but the post-navigation introspection could not complete — the caller knows the back-action ran but gets no page data.","triggerScenarios":"The execution context is destroyed or busy while the navigated page is still loading (page_info's run_js fails), the new document crashed, the CDP connection dropped between the back() call and page_info(), or the previous page has a beforeunload/redirect that invalidates the context during evaluation.","commonSituations":"Going back to a heavy page that takes >500ms+poll window to reach an evaluable state; returning to a page that immediately redirects (context destroyed mid-eval); flaky CDP sessions in long-running automation; cross-origin previous page with a crash-prone script.","solutions":["Retry the back command — page_info usually succeeds once the load settles.","Increase settle time before relying on the result: run a wait on document.readyState or a known selector of the previous page, then call read_page/page_info separately.","Check the inner {e}: 'Execution context was destroyed' means wait longer after history.back(); connection errors mean re-establish the CDP session.","If the page redirects, wait for the final URL to stabilize before requesting page info.","Catch this error and treat the navigation as successful-but-unverified; re-query page state with a dedicated command instead of failing the whole step."],"exampleFix":"// before: assume back gives info atomically\nlet resp = browser.cmd_back();\n// after: tolerate partial failure and re-query\nlet resp = match browser.cmd_back() {\n    r if r.is_err() && r.err().contains(\"page info failed\") => {\n        browser.wait_for_load().await;\n        browser.page_info_command() // retry info separately\n    }\n    r => r,\n};","handlingStrategy":"fallback","validationCode":"let ready = browser.cmd_run_js(\"document.readyState\");\nif ready.is_err() { /* context not evaluable yet — do not call back() yet, or expect info retry */ }","typeGuard":"fn is_back_info_failure(resp: &BrowserResponse) -> bool {\n    resp.error.as_deref().map(|e| e.starts_with(\"Back succeeded but page info failed\")).unwrap_or(false)\n}","tryCatchPattern":"match browser.cmd_back() {\n    Ok(info) => info,\n    Err(e) if e.contains(\"page info failed\") => {\n        wait_for_load();\n        browser.read_page() // navigation succeeded; re-fetch info\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Treat this as partial success: navigation happened, only introspection failed — retry info, not the back action.","Avoid stacking back() calls faster than pages can settle; wait for readyState between steps.","Watch for pages that redirect on load; wait for URL stability before reading page info.","Use a known selector of the destination page as a readiness signal before requesting info.","Log the inner error to distinguish context-destroyed (timing) from connection-lost (session) causes."],"tags":["browser","navigation","cdp","page-info"],"backgroundTag":"context-destroyed","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}