apify/crawlee · error
No browser context available
Error message
No browser context available
What it means
StagehandController._newPage() connects to the browser over CDP and needs Playwright's default browser context to spawn new pages. When this.browser.contexts() returns an empty array there is no context to create pages from, so the controller throws immediately before attempting newPage().
Source
Thrown at packages/stagehand-crawler/src/internals/stagehand-controller.ts:54
if (!this.#stagehand) {
this.#stagehand = this.#stagehandInstances.get(this.browser)!;
if (!this.#stagehand) {
throw new Error('Stagehand instance not found for browser');
}
}
return this.#stagehand;
}
/**
* Creates a new page using the browser's default context.
* We use Playwright's browser API directly since we connected via CDP.
*/
protected override async _newPage(_contextOptions?: unknown): Promise<Page> {
try {
// Get the default context from the Playwright browser (connected via CDP)
const contexts = this.browser.contexts();
if (contexts.length === 0) {
throw new Error('No browser context available');
}
const context = contexts[0];
const page = await context.newPage();
// Track active pages
page.once('close', () => {
this.activePages--;
});
try {
await this.waitForStagehandToRegisterPage(page);
} catch (error) {
await page.close().catch(() => {});
throw error;
}
return page;View on GitHub (pinned to dbe57fb09c)
Solutions
- Verify the Stagehand-managed browser is still running and the CDP connection is alive before crawling
- Ensure StagehandPlugin._launch succeeded and chromium.connectOverCDP(cdpUrl) returned a browser with contexts (log browser.contexts().length)
- Recreate the browser (restart the pool / crawler) if the underlying Chrome process died
- Check for code that calls browser.contexts()[0].close() or newContext cleanup that empties the context list
Example fix
// before
const page = await crawler.browserPool.newPage(); // browser already dead
// after
if (!browser.isConnected()) {
await browserPool.retireBrowser(browser); // force pool to open a fresh one
}
const page = await crawler.browserPool.newPage(); Defensive patterns
Strategy: validation
Validate before calling
if (!browser.isConnected?.() || browser.contexts().length === 0) {
throw new Error('Browser has no contexts; cannot create pages');
} Type guard
const hasUsableContext = (browser) =>
typeof browser?.contexts === 'function' && browser.contexts().length > 0; Try / catch
try {
const page = await browserPool.newPage();
} catch (err) {
if (err.message.includes('No browser context available')) {
await browserPool.retireActiveBrowsers(); // recycle dead browser
}
throw err;
} Prevention
- Check browser.isConnected() before heavy page creation
- Avoid manually closing the default context
- Recycle/retire browsers that crashed instead of reusing them
- Monitor CDP connection health for long crawls
When it happens
Trigger: Calling _newPage (triggered by the browser pool opening a new page) on a browser connected via connectOverCDP that reported zero contexts — e.g. the CDP connection attached without a default context, the browser was closed between connect and newPage, or all contexts were closed explicitly.
Common situations: Chromium crashed/exited during the run leaving a dead CDP connection, connecting to a remote browser that has no open targets, race where browser.close() runs while the pool still requests pages, or a custom browser plugin returning a context-less browser.
Related errors
- Function `newBrowserCDPSession()` is not available in incogn
- Failed to create new page: ${error instanceof Error ? error.
- Stagehand did not register the page within ${timeoutMs}ms
- Failed to get CDP URL from Stagehand
- Function `newContext()` is not available in incognito mode
AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30).
Data as JSON: /api/errors/d58c4056856e6b1e.
Report an issue: GitHub.