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

  1. Verify the Stagehand-managed browser is still running and the CDP connection is alive before crawling
  2. Ensure StagehandPlugin._launch succeeded and chromium.connectOverCDP(cdpUrl) returned a browser with contexts (log browser.contexts().length)
  3. Recreate the browser (restart the pool / crawler) if the underlying Chrome process died
  4. 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

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


AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30). Data as JSON: /api/errors/d58c4056856e6b1e. Report an issue: GitHub.