{"record":{"id":"f8cab8f1f1962b53","repo":"apify/crawlee","slug":"browsercontroller-newpage-failed-browsercontr","errorCode":null,"errorMessage":"browserController.newPage() failed: ${browserController.id}\nCause:${(err as Error).message}.","messagePattern":"browserController\\.newPage\\(\\) failed: (.+?)\nCause:(.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser-pool/src/browser-pool.ts","lineNumber":643,"sourceCode":"                async () => browserController.newPage(finalPageOptions),\n                this.operationTimeoutMillis,\n                'browserController.newPage() timed out.',\n            )) as PageReturn;\n            tryCancel();\n\n            this.pages.set(pageId, page);\n            this.pageIds.set(page, pageId);\n            this.pageToBrowserController.set(page, browserController);\n\n            // if you synchronously trigger a lot of page launches, browser will not get retired soon enough. Not sure if it's a problem, let's monitor it.\n            if (browserController.totalPages >= this.retireBrowserAfterPageCount) {\n                this.retireBrowserController(browserController);\n            }\n\n            this.overridePageClose(page);\n        } catch (err) {\n            this.retireBrowserController(browserController);\n            throw new Error(\n                `browserController.newPage() failed: ${browserController.id}\\nCause:${(err as Error).message}.`,\n            );\n        }\n\n        await this.executeHooks(this.postPageCreateHooks, page, browserController);\n        tryCancel();\n\n        this.emit(BROWSER_POOL_EVENTS.PAGE_CREATED, page);\n\n        return page;\n    }\n\n    /**\n     * Removes a browser controller from the pool. The underlying\n     * browser will be closed after all its pages are closed.\n     *\n     */\n    retireBrowserController(browserController: BrowserControllerReturn): void {","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/browser-pool/src/browser-pool.ts#L625-L661","documentation":"createPageForBrowser wraps browserController.newPage(); if the underlying controller fails to open a page (browser crashed, context closed, CDP error, navigation/timeout in controller internals), the pool retires the browser controller and rethrows a plain Error that embeds the controller id and the original message. The original error becomes part of the message text (after 'Cause:'), not error.cause.","triggerScenarios":"browserController.newPage() throwing inside createPageForBrowser — reached via pool.newPage() or pool.newPageInNewBrowser() — e.g. browser process crashed or disconnected, context/page target closed, or plugin-specific newPage failure.","commonSituations":"Browser killed by OOM in constrained containers; remote browser connection dropped mid-session; too many concurrent pages exhausting the browser; puppeteer/playwright TargetClosedError after crash.","solutions":["Parse the message after 'Cause:' (or catch and read err.message) to find the root failure.","Retry the page creation — the failed controller was already retired so the pool will launch a fresh browser.","Reduce concurrent page count / increase container memory if the cause is OOM or resource exhaustion.","For remote browsers, verify connectivity and consider connection retry/backoff before launching."],"exampleFix":"// before\nawait pool.newPage(); // may throw 'browserController.newPage() failed: ...\nCause:Target closed'\n// after\nlet page;\ntry {\n    page = await pool.newPage();\n} catch (err) {\n    console.warn('page creation failed, retrying with fresh browser:', err.message);\n    page = await pool.newPage(); // retired controller ensures a new browser is launched\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    page = await pool.newPage();\n} catch (err) {\n    if (err.message.startsWith('browserController.newPage() failed')) {\n        const cause = err.message.split('Cause:')[1];\n        console.warn('newPage failed:', cause, '— retrying (controller retired)');\n        page = await pool.newPage();\n    } else throw err;\n}","preventionTips":["Retry once — the pool already retired the bad controller and will launch a fresh browser","Monitor memory/OOM in containers; cap concurrency to avoid browser crashes","Keep remote connections stable; add network retry/backoff for remote browsers"],"tags":["page-creation","browser-crash","retry"],"backgroundTag":"browser-page-open-failed","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}