{"record":{"id":"d00f850a45c33eb0","repo":"karatelabs/karate","slug":"navigation-aborted-by-browser-current-document-retained","errorCode":null,"errorMessage":"navigation aborted by browser, current document retained: {}","messagePattern":"navigation aborted by browser, current document retained: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java","lineNumber":1324,"sourceCode":"                throw e;\n            }\n            aborted = \"net::ERR_ABORTED\".equals(navResponse.getResultAsString(\"errorText\"));\n            if (!aborted) {\n                break; // committed, an error page under the same loader, or a normal response\n            }\n            if (attempt < navAttempts - 1) {\n                logger.warn(\"Page.navigate returned ERR_ABORTED, retrying ({}/{}): {}\", attempt + 1, navAttempts - 1, url);\n                sleep(150); // let an in-flight/racing navigation (e.g. pooled-reset about:blank) settle\n            }\n        }\n\n        // Every attempt aborted — a deliberate download / 204-205 / window.stop() that\n        // retains the current document. The returned loader never commits, never fires\n        // DOMContentLoaded, and a loader-bound wait for it could only end in a timeout,\n        // so return with the page as-is (genuine load failures instead commit an error\n        // page under the SAME loader, and the normal wait below handles those).\n        if (aborted) {\n            logger.warn(\"navigation aborted by browser, current document retained: {}\", url);\n            pendingNavigationUrl = null;\n            return;\n        }\n\n        // data: and about: URLs commit locally and don't fire the normal load lifecycle,\n        // so the full waitForPageLoad below would only ever time out on them. Returning\n        // with no barrier at all is what let the pooled reset's about:blank still be in\n        // flight when the scenario's first real navigation was issued: Chrome aborted one\n        // against the other (net::ERR_ABORTED clustered on the post-reset /input, /wait,\n        // /shadow-dom navigations) and the scenario continued against whichever document\n        // won that race. Barrier on THIS navigation actually committing instead — cheap,\n        // since a local document commits in milliseconds.\n        //\n        // Best-effort and bounded: if the commit signal never arrives we proceed anyway,\n        // which is no worse than the unconditional return this replaces.\n        if (url.startsWith(\"data:\") || url.startsWith(\"about:\")) {\n            String localLoaderId = navResponse.getResultAsString(\"loaderId\");\n            if (localLoaderId != null && !pollUntil(LOCAL_NAV_COMMIT_TIMEOUT_MS, 10,","sourceCodeStart":1306,"sourceCodeEnd":1342,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java#L1306-L1342","documentation":"After all Page.navigate retry attempts return net::ERR_ABORTED, the driver concludes the browser deliberately retained the current document (download, 204/205 response, or window.stop()) and logs this warning instead of waiting for a load event that will never fire. The method returns normally with the page as-is; it does not throw. Loader-bound waits are skipped because the returned loader never commits and DOMContentLoaded would never arrive.","triggerScenarios":"All navAttempts of driver.get()/loadUrl() end with errorText 'net::ERR_ABORTED', so the 'aborted' flag is still true after the retry loop.","commonSituations":"Navigating to a CSV/PDF link that downloads instead of rendering, endpoints returning 204 No Content, SPA code calling window.stop() during load, or an external link intercepted by a service worker.","solutions":["Use Karate HTTP steps or driver.download for URLs that return files or 204/205 instead of documents.","Remove or condition window.stop() in the page under test.","Verify the URL actually serves an HTML document (curl -I to check Content-Disposition/status).","If you expect a document but see this, retry the navigation; a racing reset may have aborted it."],"exampleFix":"// before\ndriver.get('https://host/api/export'); // 204 or download, navigation aborted\n// after\nkarate.call('classpath:helpers/download.feature'){ // use HTTP/download flow for non-document responses\n  def resp = karate.http('https://host/api/export').get();\n}","handlingStrategy":"fallback","validationCode":"var resp = karate.http(url).get(); if (resp.status == 204 || resp.header('content-disposition') != null) { /* use HTTP flow, not driver.get */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use karate HTTP steps for downloads and 204/205 endpoints","Verify Content-Type is a document before driver.get()","Remove window.stop() from test pages","Re-navigate to a real document afterwards if you need DOM access"],"tags":["cdp","navigation","err-aborted","download"],"backgroundTag":"navigation-aborted","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}