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 the page's screenshot and/or HTML content into a KeyValueStore, and wraps any failure (page.screenshot, page.content, or store.setValue throwing) in this single error that names the snapshot key and the underlying cause. It is a wrapper so the original error's message is preserved after 'Cause:'.

Source

Thrown at packages/puppeteer-crawler/src/internals/utils/puppeteer_utils.ts:777

        });

        if (saveScreenshot) {
            const screenshotName = `${key}.jpg`;
            const screenshotBuffer = await page.screenshot({
                fullPage: true,
                quality: screenshotQuality,
                type: 'jpeg',
            });
            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}`);
    }
}

export interface PuppeteerContextUtils {
    /**
     * Injects a JavaScript file into current `page`.
     * Unlike Puppeteer's `addScriptTag` function, this function works on pages
     * with arbitrary Cross-Origin Resource Sharing (CORS) policies.
     *
     * File contents are cached for up to 10 files to limit file system access.
     */
    injectFile(filePath: string, options?: InjectFileOptions): Promise<unknown>;

    /**
     * Injects the [jQuery](https://jquery.com/) library into current `page`.
     * jQuery is often useful for various web scraping and crawling tasks.
     * For example, it can help extract text from HTML elements using CSS selectors.
     *

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Read the 'Cause:' suffix to find the real error and fix that root cause first
  2. Validate the snapshot key (no '/', '\\', or other invalid KeyValueStore characters)
  3. Pass explicit options like screenshot timeout: saveSnapshot({ ..., timeout: 60000 })
  4. Check that the browser/page is still open before snapshotting (page.isClosed())
  5. Ensure the KeyValueStore (local or cloud) is writable and credentials/quota are fine

Example fix

// before
await saveSnapshot({ page, key });
// after
try {
    await saveSnapshot({ page, key, savePng: true, saveHtml: true, timeout: 60_000 });
} catch (err) {
    getLog().warning(`Snapshot ${key} skipped: ${err.message}`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

function canSnapshot(page, key) {
    return typeof page?.content === 'function' && !page.isClosed?.() && key && !/[\\/:*?"<>|]/.test(key);
}

Type guard

const isValidSnapshotInput = (input) =>
    input && typeof input.page?.content === 'function' && typeof input.key === 'string' && input.key.length > 0;

Try / catch

try {
    await saveSnapshot({ page, key, savePng: true, saveHtml: true });
} catch (err) {
    log.warning(`snapshot ${key} skipped: ${err.message.split('Cause:')[1] ?? err.message}`);
}

Prevention

When it happens

Trigger: Calling saveSnapshot({ page, key, saveHtml/savePng }) when the underlying store write fails (KeyValueStore unavailable, invalid key characters), the browser/page is closed or crashed before capture, page.content() fails on a detached/navigating frame, or screenshot times out on a hung page.

Common situations: Snapshotting in a finally block after a page crash, invalid keys containing path separators, slow pages exceeding the default screenshot timeout, and browser disconnected mid-crawl.

Related errors


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