apify/crawlee · error

saveSnapshot with key ${key} failed. Cause:${(err as Error).

Error message

saveSnapshot with key ${key} failed.
Cause:${(err as Error).message}

What it means

saveSnapshot captures a page screenshot and/or HTML into a key-value store. Any failure during page.screenshot(), page.content(), or store.setValue() is caught and re-thrown wrapped in this error that names the snapshot key and the underlying cause, so failures are attributable to a specific snapshot.

Source

Thrown at packages/playwright-crawler/src/internals/utils/playwright-utils.ts:564

        if (saveScreenshot) {
            const screenshotName = `${key}.jpg`;
            const screenshotBuffer = await page.screenshot({
                fullPage: true,
                quality: screenshotQuality,
                type: 'jpeg',
                animations: 'disabled',
            });
            await store.setValue(screenshotName, screenshotBuffer, { contentType: 'image/jpeg' });
        }

        if (saveHtml) {
            const htmlName = `${key}.html`;
            const html = await page.content();
            await store.setValue(htmlName, html, { contentType: 'text/html' });
        }
    } catch (err) {
        throw new Error(`saveSnapshot with key ${key} failed.\nCause:${(err as Error).message}`);
    }
}

/**
 * Returns Cheerio handle for `page.content()`, allowing to work with the data same way as with {@apilink CheerioCrawler}.
 *
 * **Example usage:**
 * ```javascript
 * const $ = await playwrightUtils.parseWithCheerio(page);
 * const title = $('title').text();
 * ```
 *
 * @param page Playwright [`Page`](https://playwright.dev/docs/api/class-page) object.
 * @param ignoreShadowRoots
 */
export async function parseWithCheerio(
    page: Page,
    ignoreShadowRoots = false,

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Read the `Cause:` suffix of the message to identify the underlying error and fix it (page state, storage, permissions).
  2. Guard saveSnapshot calls: check page.isClosed() (or !page.isClosed()) before snapshotting.
  3. Wrap snapshot calls in try/catch when snapshots are best-effort and should not fail the request.
  4. Use unique snapshot keys (e.g., include request.id) to avoid store conflicts.

Example fix

// before
await context.saveSnapshot({ key: 'snapshot' });
// after
try {
    if (!context.page.isClosed()) {
        await context.saveSnapshot({ key: `snapshot-${context.request.id}` });
    }
} catch (err) {
    log.warning(`Snapshot skipped: ${(err as Error).message}`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-checks before snapshot
if (!page || page.isClosed()) return; // skip snapshot

Type guard

function canSnapshot(page: Page | undefined): page is Page {
    return !!page && !page.isClosed();
}

Try / catch

try {
    await context.saveSnapshot({ key: `snap-${context.request.id}` });
} catch (err) {
    log.warning(`Snapshot failed, continuing: ${(err as Error).message}`); // cause is embedded after 'Cause:'
}

Prevention

When it happens

Trigger: Calling context.saveSnapshot() (or saveSnapshot util) when the page is closed/crashed mid-navigation, the screenshot cannot be taken (invalid CDP state), or the key-value store is unavailable/read-only.

Common situations: Snapshot taken after navigation destroyed the page; storage quota or permissions issues in managed environments; concurrent setValue on the same key; saving snapshots of pages closed by a timeout.

Related errors


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