apify/crawlee · error · ContextPipelineInitializationError

The current SessionPool instance couldn't find a valid sessi

Error message

The current SessionPool instance couldn't find a valid session for the following id: ${request.sessionId}.

What it means

resolveSession retries fetching the session identified by `request.sessionId` from the SessionPool; if the pool cannot produce a valid session for that id within the internal timeout, the request fails with a MissingSessionError wrapped in ContextPipelineInitializationError. This typically means the session was retired/invalidated and the pool has no usable replacement.

Source

Thrown at packages/basic-crawler/src/internals/basic-crawler.ts:1527

            this.internalTimeoutMillis,
            `Fetching next request timed out after ${this.internalTimeoutMillis / 1e3} seconds.`,
        );

        // Reset loadedUrl so an old one is not carried over to retries.
        if (request) {
            request.loadedUrl = undefined;
        }

        return request;
    }

    private async resolveSession({ request }: { request: Request }) {
        const session = await this.timeoutAndRetry(
            async () => {
                const existingSession = await this.sessionPool.getSession(request.sessionId);

                if (!existingSession) {
                    throw new ContextPipelineInitializationError(new MissingSessionError(request.sessionId));
                }

                return existingSession;
            },
            this.internalTimeoutMillis,
            `Fetching session timed out after ${this.internalTimeoutMillis / 1e3} seconds.`,
        );

        return { session, proxyInfo: session?.proxyInfo };
    }

    private async createContextHelpers({ request, session }: { request: Request; session: ISession }) {
        const addRequests: CrawlingContext['addRequests'] = async (requests, options = {}) => {
            const newCrawlDepth = request!.crawlDepth + 1;
            const requestsGenerator = this.addCrawlDepthRequestGenerator(requests, newCrawlDepth);

            return await this.addRequests(requestsGenerator, options);
        };

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Let the crawler assign sessions itself — remove a stale hardcoded `sessionId` from the request so a fresh one is allocated.
  2. Increase sessionPool `maxPoolSize` or session `maxAgeSeconds` so valid sessions outlive the queue backlog.
  3. Persist and restore the SessionPool (same storage) between runs so old sessionIds remain resolvable.
  4. Clear `request.sessionId` in a request-handler retry path when a session is known to have been retired.

Example fix

// before (reusing stale session across restarts)
await crawler.addRequests([{ url, sessionId: 'sess-123' }]);
// after (let the pool pick a valid session)
await crawler.addRequests([{ url }]);
Defensive patterns

Strategy: retry

Try / catch

try {
  await crawler.run(requests);
} catch (err) {
  if (err instanceof ContextPipelineInitializationError && err.message.includes('valid session')) {
    // drop stale sessionId from the request and re-enqueue it
    delete request.sessionId;
    await crawler.addRequests([request]);
  } else throw err;
}

Prevention

When it happens

Trigger: A request carries a `sessionId` that no longer exists in the SessionPool (session expired, pool purged, or session pool recreated between runs), and repeated `sessionPool.getSession(id)` calls return null until the internal timeout elapses.

Common situations: Long-running crawls where sessions rotate; persisting requests with sessionId across crawler restarts into a fresh session pool; session pool max age smaller than crawl duration.

Related errors


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