apify/crawlee · error

Could not resolve StagehandController for page — is the brow

Error message

Could not resolve StagehandController for page — is the browser pool configured correctly?

What it means

setUpStagehand() maps a crawling context's page back to its StagehandController via getBrowserControllerByPage() to fetch the Stagehand instance. When no controller is registered for that page, the crawler cannot proceed and throws this error hinting at a browser pool misconfiguration.

Source

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

                this.browserPool as unknown as {
                    getBrowserControllerByPage(page: StagehandPage): StagehandController | undefined;
                }
            ).getBrowserControllerByPage(page);
        }

        return undefined;
    }

    /**
     * Enhance the page with Stagehand AI methods.
     */
    private async setUpStagehand(crawlingContext: {
        page: Page;
    }): Promise<{ stagehand: Stagehand; page: StagehandPage }> {
        const controller = this.getBrowserControllerByPage(crawlingContext.page as StagehandPage);

        if (!controller) {
            throw new Error(
                'Could not resolve StagehandController for page — is the browser pool configured correctly?',
            );
        }

        const stagehand = controller.getStagehand();

        return {
            stagehand,
            page: enhancePageWithStagehand(crawlingContext.page, stagehand),
        };
    }

    /**
     * Navigation handler for Stagehand crawler.
     * Uses standard Playwright navigation.
     */
    protected override async navigationHandler(
        crawlingContext: StagehandCrawlingContext,

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Ensure the browser pool uses StagehandPlugin so pages get a StagehandController
  2. Create all pages through the crawler/browser pool, never manually via playwright.chromium.launch()
  3. Confirm you call enhancedPage helpers only on pages the same StagehandCrawler instance created
  4. If using a custom page-generating plugin, wrap it so it delegates registration to StagehandController

Example fix

// before
browserPoolOptions: { browserPlugins: [new PlaywrightPlugin(chromium.launchOptions)] }
// after
browserPoolOptions: { browserPlugins: [new StagehandPlugin()] }
Defensive patterns

Strategy: validation

Validate before calling

const controller = crawler.getBrowserControllerByPage(page);
if (!controller) {
    throw new Error('page is not managed by the Stagehand browser pool; aborting stagehand setup');
}

Type guard

const isPoolPage = (crawler, page) =>
    typeof crawler.getBrowserControllerByPage === 'function' &&
    crawler.getBrowserControllerByPage(page) != null;

Try / catch

try {
    const { stagehand, page: spage } = await crawler.setUpStagehand(ctx);
} catch (err) {
    if (err.message.includes('Could not resolve StagehandController')) {
        throw new Error('Configure browserPoolOptions.browserPlugins with StagehandPlugin');
    }
    throw err;
}

Prevention

When it happens

Trigger: Using a page inside requestHandler that did not originate from the Stagehand browser pool — e.g. a page created manually via playwright, pages created before the plugin registered controllers, or mixing StagehandCrawler with a custom browserPoolOptions browser plugin (default Playwright/Puppeteer plugin).

Common situations: Configuring browserPoolOptions with plain chromiumLauncherPlugin instead of StagehandPlugin, running pages through a different crawler instance, or passing foreign page objects to enhanced page utilities.

Related errors


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