{"record":{"id":"9d66dda7c9be9ec6","repo":"RightNow-AI/openfang","slug":"navigate-succeeded-but-page-info-failed-e","errorCode":null,"errorMessage":"Navigate succeeded but page info failed: {e}","messagePattern":"Navigate succeeded but page info failed: (.+?)","errorType":"http","errorClass":"BrowserResponse","httpStatus":null,"severity":"warning","filePath":"crates/openfang-runtime/src/browser.rs","lineNumber":433,"sourceCode":"\n    // ── Command implementations ────────────────────────────────────────\n\n    async fn cmd_navigate(&self, url: &str) -> BrowserResponse {\n        let result = self\n            .cdp\n            .send(\"Page.navigate\", serde_json::json!({ \"url\": url }))\n            .await;\n\n        if let Err(e) = result {\n            return BrowserResponse::err(format!(\"Navigate failed: {e}\"));\n        }\n\n        // Wait for page load\n        self.wait_for_load().await;\n\n        match self.page_info().await {\n            Ok(info) => BrowserResponse::ok(info),\n            Err(e) => BrowserResponse::err(format!(\"Navigate succeeded but page info failed: {e}\")),\n        }\n    }\n\n    async fn cmd_click(&self, selector: &str) -> BrowserResponse {\n        let sel_json = serde_json::to_string(selector).unwrap_or_default();\n        let js = format!(\n            r#\"(() => {{\n    let sel = {sel_json};\n    let el = document.querySelector(sel);\n    if (!el) {{\n        const all = document.querySelectorAll('a, button, [role=\"button\"], input[type=\"submit\"], [onclick]');\n        const lower = sel.toLowerCase();\n        for (const e of all) {{\n            if (e.textContent.trim().toLowerCase().includes(lower)) {{ el = e; break; }}\n        }}\n    }}\n    if (!el) return JSON.stringify({{success: false, error: 'Element not found: ' + sel}});\n    el.scrollIntoView({{block: 'center'}});","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-runtime/src/browser.rs#L415-L451","documentation":"After a successful Page.navigate and wait_for_load, cmd_navigate calls page_info() to fetch the current page metadata (URL/title). If that CDP-backed call fails, this error distinguishes 'navigation worked but introspection failed' from a plain navigation failure, so the caller knows the page may actually be loaded.","triggerScenarios":"Page.navigate succeeded and wait_for_load completed, but self.page_info().await returned Err — typically a CDP evaluation failure while collecting page info (e.g. page navigated again, crashed, or context destroyed mid-query).","commonSituations":"SPA redirects or meta-refresh firing after load completes; page crash (out of memory) right after navigation; extension/script destroying the JS context during page_info evaluation.","solutions":["Retry page_info after a short delay — the page may still be settling after load.","Treat the navigation as successful and read the URL/title via a separate, retried CDP call.","Increase wait_for_load tolerance or poll for document.readyState before querying page info.","Check the inner error for 'context destroyed' style messages indicating a page crash."],"exampleFix":"// before\nmatch self.page_info().await {\n    Ok(info) => BrowserResponse::ok(info),\n    Err(e) => BrowserResponse::err(format!(\"Navigate succeeded but page info failed: {e}\")),\n}\n// after\nmatch self.page_info().await {\n    Ok(info) => BrowserResponse::ok(info),\n    Err(_) => {\n        tokio::time::sleep(std::time::Duration::from_millis(500)).await;\n        match self.page_info().await {\n            Ok(info) => BrowserResponse::ok(info),\n            Err(e) => BrowserResponse::err(format!(\"Navigate succeeded but page info failed: {e}\")),\n        }\n    }\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":"fn page_info_available(resp: &BrowserResponse) -> bool {\n    resp.success && resp.value.get(\"url\").is_some()\n}","tryCatchPattern":"// Rust\nmatch browser.execute(\"navigate\", url).await {\n    Ok(r) if r.success && r.value.get(\"url\").is_some() => Ok(r),\n    Ok(r) if r.success => {\n        // navigation worked, page_info failed — retry info once, else continue\n        tokio::time::sleep(Duration::from_millis(500)).await;\n        browser.execute(\"page_info\", \"\").await.map_err(Into::into)\n    }\n    Ok(r) => Err(anyhow!(r.error)),\n    Err(e) => Err(e.into()),\n}","preventionTips":["Poll document.readyState == \"complete\" before reading page info.","Add a short settle delay after wait_for_load on SPA-heavy sites.","Treat page-info failure as non-fatal when you only need the navigation itself.","Watch for 'context destroyed' errors as a signal of page crashes."],"tags":["cdp","page-info","race-condition"],"backgroundTag":"page-context-destroyed","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}