apify/crawlee · error

Failed to create new page: ${error instanceof Error ? error.

Error message

Failed to create new page: ${error instanceof Error ? error.message : String(error)}

What it means

Generic wrapper for any error thrown inside StagehandController._newPage(). Every failure while creating a page (no context, context.newPage() failing, post-creation steps like waitForStagehandToRegisterPage throwing, cleanup page.close() races) is rethrown as 'Failed to create new page: <cause>' with the original error attached via { cause }.

Source

Thrown at packages/stagehand-crawler/src/internals/stagehand-controller.ts:74

            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;
        } catch (error) {
            throw new Error(`Failed to create new page: ${error instanceof Error ? error.message : String(error)}`, {
                cause: error,
            });
        }
    }

    /**
     * Waits until Stagehand knows about the page, so that `act()`/`extract()`/`observe()` can resolve it.
     *
     * Stagehand only learns about pages from CDP `Target.attachedToTarget` events on its own connection,
     * and it maps them by main frame id. We create pages through a separate `connectOverCDP()` handle, so
     * `context.newPage()` resolves before Stagehand has processed that event — the page is unresolvable for
     * a short window, and the AI methods fail with 'Failed to resolve V3 Page from Playwright page'.
     * Stagehand's own `newPage()` polls for the same reason.
     */
    private async waitForStagehandToRegisterPage(page: Page, timeoutMs = 10_000): Promise<void> {
        const stagehand = this.getStagehand();
        const mainFrameId = await this.getMainFrameId(page);
        const deadline = Date.now() + timeoutMs;

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Inspect the interpolated message and err.cause to identify the root error, then fix that
  2. If cause is a registration timeout, check that Stagehand can attach its CDP helper script (no conflicting extensions/interception)
  3. If the browser crashed, restart the crawler / recycle the browser pool
  4. Catch this in a requestHandler error path and retire the page so the pool can spawn a new one

Example fix

// before
const page = await browserPool.newPage(); // throws opaque wrapper
// after
try {
    const page = await browserPool.newPage();
} catch (err) {
    log.error('newPage failed', err.cause ?? err); // see root cause
    throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const canCreate = browser?.isConnected?.() && browser.contexts().length > 0;
if (!canCreate) throw new Error('skip newPage: browser not ready');

Type guard

const isWrappedPageError = (e) => e instanceof Error && e.message.startsWith('Failed to create new page:');

Try / catch

try {
    const page = await browserPool.newPage();
} catch (err) {
    if (isWrappedPageError(err)) {
        log.error('page creation failed', err.cause ?? err); // root cause in .cause
        await browserPool.retireActiveBrowsers();
    }
    throw err;
}

Prevention

When it happens

Trigger: Any failure during new page creation: 'No browser context available', context.newPage() throwing (browser disconnected/crashed), or waitForStagehandToRegisterPage timing out ('Stagehand did not register the page within Nms').

Common situations: Debugging StagehandCrawler page-creation failures where the log only shows this wrapper — the actionable info is in the message suffix or err.cause.

Related errors


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