apify/crawlee · error

The `${prop}` property is not available on the outer context

Error message

The `${prop}` property is not available on the outer context pipeline of AdaptivePlaywrightCrawler - it is provided by the inner (static/browser) pipelines

What it means

AdaptivePlaywrightCrawler composes an outer pipeline whose context only guarantees `request`; browser/static-specific helpers like `response` are intentionally absent there and throw via `errorMessage('response')`. The real `response` object is only provided by the inner static/browser pipelines once rendering mode is chosen. Accessing `context.response` on the outer context means you got a context object that has not been specialized.

Source

Thrown at packages/playwright-crawler/src/internals/adaptive-playwright-crawler.ts:485

    protected override async init(): Promise<void> {
        // Only the predictor we built ourselves is ours to initialize - an injected one is borrowed, so its
        // lifecycle (including restoring persisted state) stays with whoever created it.
        await this.#renderingTypePredictor.ifOwned((predictor) => predictor.initialize());
        return await super.init();
    }

    protected override buildContextPipeline(): ContextPipeline<CrawlingContext, AdaptivePlaywrightCrawlerContext> {
        const errorMessage = (prop: string) =>
            `The \`${prop}\` property is not available on the outer context pipeline of AdaptivePlaywrightCrawler - it is provided by the inner (static/browser) pipelines`;

        return super.buildContextPipeline().compose({
            action: async ({ request }) => ({
                get request(): LoadedRequest<Request<Dictionary>> {
                    return request as LoadedRequest<Request<Dictionary>>;
                },
                get response(): Response {
                    throw new Error(errorMessage('response'));
                },
                get page(): Page {
                    throw new Error(errorMessage('page'));
                },
                get querySelector(): AdaptivePlaywrightCrawlerContext['querySelector'] {
                    throw new Error(errorMessage('querySelector'));
                },
                get querySelectorAll(): AdaptivePlaywrightCrawlerContext['querySelectorAll'] {
                    throw new Error(errorMessage('querySelectorAll'));
                },
                get waitForSelector(): AdaptivePlaywrightCrawlerContext['waitForSelector'] {
                    throw new Error(errorMessage('waitForSelector'));
                },
                get parseWithCheerio(): AdaptivePlaywrightCrawlerContext['parseWithCheerio'] {
                    throw new Error(errorMessage('parseWithCheerio'));
                },
                get enqueueLinks(): AdaptivePlaywrightCrawlerContext['enqueueLinks'] {
                    throw new Error(errorMessage('enqueueLinks'));

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Access `response` inside the `requestHandler` of the specialized pipeline, where the inner context provides it.
  2. Use `context.request.loadedUrl` or read response data within the handler instead of hooks/outer-context code.
  3. If you need the raw HTTP response deterministically, use CheerioCrawler (or PlaywrightCrawler) instead of the adaptive variant.
  4. Guard with a feature check: `if ('response' in context && context.response)` before use.

Example fix

// before (in a pre-navigation hook)
preNavigationHooks: [async (ctx) => { console.log(ctx.response.status); }]

// after (inside requestHandler)
async requestHandler(ctx) {
    const status = ctx.response?.status;
}
Defensive patterns

Strategy: try-catch

Type guard

function hasResponse(ctx: unknown): ctx is { response: Response } {
    try {
        return Boolean((ctx as { response?: unknown }).response);
    } catch {
        return false;
    }
}

Try / catch

try {
    const res = context.response;
    processResponse(res);
} catch (err) {
    if (err.message.includes('not available on the outer context')) {
        log.warning('response only exists inside the specialized requestHandler context.');
    } else {
        throw err;
    }
}

Prevention

When it happens

Trigger: Accessing `crawlingContext.response` in code that runs against the outer AdaptivePlaywrightCrawler context — e.g. in `preNavigationHooks`/global hooks, `requestHandler` wrappers that receive the outer context, or `ContextHelper` usage outside the specialized pipelines.

Common situations: Migrating code from PlaywrightCrawler (where `context.response` always exists) to AdaptivePlaywrightCrawler; accessing response in hooks that execute before the inner pipeline builds the context; storing the context and reading `response` later.

Related errors


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