Profiles·Public

puppeteer

semver>=1.0.0postconditions19functions19last verified2026-06-23coverage score100%

Postconditions: what we check

  • launch · launch-rejects-on-error
    error
    Whenbrowser launch fails (timeout, protocol error, missing Chrome)
    ThrowsPromise rejection with TimeoutError, ProtocolError, or Error
    Required handlingCaller MUST use try-catch to handle Promise rejections from puppeteer.launch(). Common failures: timeout (default 30s), protocol errors in Docker/containers, missing Chrome binary. Browser instance MUST be closed in finally block to prevent zombie processes. Use pattern: let browser; try { browser = await puppeteer.launch(); } catch (error) { /* handle */ } finally { if (browser) await browser.close(); }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[1]
  • goto · goto-rejects-on-timeout
    error
    Whennavigation timeout (default 30s) or network error
    ThrowsPromise rejection with TimeoutError
    Required handlingCaller MUST use try-catch to handle Promise rejections from page.goto(). This is the #1 cause of production failures. Timeouts occur with slow networks, Cloudflare protection, heavy JavaScript pages. CRITICAL: In headless shell mode, HTTP 404/500 do NOT throw - must check response.ok(). Use pattern: const response = await page.goto(url, { timeout: 60000 }); if (!response || !response.ok()) throw new Error('Navigation failed');
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[2]
  • newPage · newpage-rejects-on-error
    error
    Whenpage creation timeout or protocol error
    ThrowsPromise rejection with ProtocolError (Target.createTarget timed out)
    Required handlingCaller MUST use try-catch to handle Promise rejections from browser.newPage(). Common in Docker/containers with rapid page creation cycles. Increase protocolTimeout in launch options for containers. Use pattern: try { const page = await browser.newPage(); } catch (error) { /* handle */ }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[3]
  • close · browser-close-must-run
    warning
    Whenbrowser instance exists after operations
    ThrowsMay throw Error if browser already closed or connection lost
    Required handlingBrowser.close() MUST be called in finally block to prevent zombie Chrome processes. Each zombie process consumes 80-90MB. Accumulation causes memory exhaustion and server crashes. Close can itself throw errors - wrap in try-catch within finally to avoid masking original errors. Use pattern: finally { if (browser) { try { await browser.close(); } catch (e) {} } }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[4]
  • waitForSelector · waitforselector-rejects-on-timeout
    warning
    Whenelement not found within timeout (default 30s)
    ThrowsPromise rejection with TimeoutError
    Required handlingCaller MUST use try-catch to handle TimeoutError from page.waitForSelector(). Timeouts common when element never appears or takes longer than expected. Consider increasing timeout for slow-loading pages. Use pattern: try { await page.waitForSelector('selector', { timeout: 10000 }); } catch (error) { /* handle */ }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[5]
  • click · click-rejects-on-error
    warning
    Whenelement not found or not clickable
    ThrowsPromise rejection with Error
    Required handlingCaller MUST use try-catch to handle errors from page.click(). Common failures: selector not found, element not clickable, element moved. CRITICAL: When click triggers navigation, use Promise.all([page.waitForNavigation(), page.click()]) to avoid race conditions. Use pattern: try { await page.click('button'); } catch (error) { /* handle */ }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[6]
  • evaluate · evaluate-execution-error
    error
    WhenJavaScript execution fails in page context (page closed, navigation during eval, unserializable return)
    ThrowsTargetCloseError if page navigated/closed during evaluation, Error if function throws in browser context
    Required handlingCaller MUST wrap page.evaluate() in try-catch. Common failures: (1) Page navigated away during evaluation — throws TargetCloseError. (2) Function throws in browser context — error propagated to Node.js. (3) Return value not serializable — throws Error. (4) Execution context destroyed (SPA navigation) — throws ProtocolError. In scraping/automation pipelines, evaluate() failures are the #1 cause of silent data loss — the scrape returns undefined instead of crashing.
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[7]
  • screenshot · screenshot-protocol-error
    error
    WhenScreenshot capture fails (page closed, protocol error, invalid options)
    ThrowsTargetCloseError if page closed during capture, Error on invalid crop/options, ProtocolError on CDP failure
    Required handlingCaller MUST wrap page.screenshot() in try-catch. Failures include: (1) Page navigated/closed during capture — TargetCloseError. (2) Invalid crop dimensions (negative, exceeds viewport) — throws Error. (3) fullPage screenshot of infinite-scroll pages — may cause OOM. (4) ProtocolError when page is mid-navigation. CRITICAL: In image generation services, unhandled screenshot errors return empty/corrupt images to users without alerting.
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[8]
  • pdf · pdf-headless-only-error
    error
    Whenpdf() called in headed (non-headless) browser mode
    ThrowsError indicating PDF generation only works in headless mode
    Required handlingCaller MUST wrap page.pdf() in try-catch. Key failure modes: (1) Called in headed mode — throws immediately. (2) Page navigated/closed during generation — TargetCloseError. (3) ProtocolError on CDP failure during rendering. CRITICAL: PDF generation services that don't catch errors return empty PDFs or crash the worker process. Always verify the returned buffer has non-zero length before serving to users.
    costhighin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[9]
  • setContent · setcontent-timeout-error
    error
    WhenPage content loading exceeds timeout (default 30s)
    ThrowsTimeoutError when waitUntil condition not met within timeout
    Required handlingCaller MUST wrap page.setContent() in try-catch. setContent() waits for the page to reach the specified load state (default: 'load'). Complex HTML with external resources can timeout. In HTML-to-PDF pipelines, timeout on setContent silently aborts the generation. Set explicit timeout and handle: page.setContent(html, { timeout: 60000 }).
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[10]
  • waitForNavigation · waitfornavigation-timeout-error
    error
    WhenNavigation does not complete within timeout (default 30s)
    ThrowsTimeoutError when navigation exceeds timeout, TargetCloseError if page closes during wait
    Required handlingCaller MUST wrap page.waitForNavigation() in try-catch. This is the most common source of flaky Puppeteer tests and production failures. Key patterns: (1) Must be called BEFORE the action that triggers navigation — use Promise.all([page.waitForNavigation(), page.click()]). (2) SPA route changes may resolve with null response. (3) Multiple rapid navigations cause race conditions. (4) Timeout in CI/Docker environments due to slow rendering.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[11]
  • waitForNetworkIdle · waitfornetworkidle-timeout-error
    warning
    WhenNetwork does not become idle within timeout
    ThrowsTimeoutError when network remains active past timeout, TargetCloseError if page closes
    Required handlingCaller MUST wrap page.waitForNetworkIdle() in try-catch. Common failures: (1) Pages with persistent WebSocket/SSE connections never reach idle — timeout guaranteed. (2) Analytics/tracking scripts continually fire requests. (3) Long-polling APIs keep network busy. Always set an explicit timeout and handle TimeoutError gracefully rather than treating it as a hard failure.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[12]
  • waitForFunction · waitforfunction-timeout-error
    warning
    WhenFunction does not return truthy value within timeout
    ThrowsTimeoutError when condition not met within timeout, TargetCloseError if page closes during wait
    Required handlingCaller MUST wrap page.waitForFunction() in try-catch. Timeout occurs when the evaluated function never returns truthy. Common in scraping when waiting for dynamic content that may not appear. The function re-evaluates on every animation frame or on DOM mutation (depending on polling option), so infinite loops in the function will not throw — they just timeout silently.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[13]
  • type · type-element-not-found
    warning
    WhenTarget element selector not found on page
    ThrowsError when no element matches the provided selector
    Required handlingCaller MUST wrap page.type() in try-catch. The method throws if the selector does not match any element. Common in form automation when pages load dynamically — always waitForSelector() before type(). Also throws TargetCloseError if page navigates during typing (e.g., auto-submit forms).
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[14]
  • $eval · eval-element-not-found
    error
    WhenNo element matches the provided selector
    ThrowsError indicating no element found for selector
    Required handlingCaller MUST wrap page.$eval() in try-catch. Unlike page.$() which returns null when no element is found, $eval() THROWS an error. This is a critical distinction — code that works with $() will crash with $eval() on missing elements. Use page.$() first to check existence, or wrap in try-catch. Common in scraping when page structure varies across different pages.
    costmediumin prodimmediate exceptionusers seedegraded performancevisibilitysilent
    Sources[15]
  • connect · connect-websocket-error
    error
    WhenWebSocket connection to browser fails (wrong URL, browser not running, network error)
    ThrowsError on WebSocket connection failure, TimeoutError if connection times out
    Required handlingCaller MUST wrap puppeteer.connect() in try-catch. Connection failures common with: (1) Browser process crashed/exited before connect. (2) Wrong WebSocket URL (port changed, container restarted). (3) Network partition between Puppeteer and remote browser. CRITICAL: In browser pool architectures, connect() failures without error handling cause the entire worker to crash instead of gracefully acquiring a new browser.
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[16]
  • executablePath · executablepath-async-rejection
    error
    WhenUnderlying launcher cannot resolve a browser binary for the host (binary missing from cache, platform unsupported, channel not installed)
    ThrowsPromise rejection with Error when the launcher's executablePath resolution fails (e.g. unknown ChromeReleaseChannel, no binary cached, unsupported platform)
    Required handlingCaller MUST wrap puppeteer.executablePath() in try-catch. CRITICAL breaking change: was synchronous in puppeteer <=24.x, became async in v25.0.0. Code that previously read the return value directly will now receive a Promise<string> and silently treat it as a path string like "[object Promise]" — passing it to spawn()/launch() fails with ENOENT. Callers that just upgraded to v25 MUST either await the result or use Promise.then. In CI/deployment scripts this is the #1 v25 migration footgun. Pattern: try { const path = await puppeteer.executablePath('chrome'); } catch (error) { /* handle */ }
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[17][18]
  • defaultArgs · defaultargs-async-rejection
    error
    WhenBrowser launcher cannot resolve the requested browser (unknown browser type, lastLaunchedBrowser unresolvable for no-arg call)
    ThrowsPromise rejection with Error when the underlying launcher cannot determine default args
    Required handlingCaller MUST wrap puppeteer.defaultArgs() in try-catch. Same v25.0.0 breaking change as executablePath() — was sync, now returns a Promise<string[]>. Code that does: const args = [...puppeteer.defaultArgs(), '--my-flag']; breaks silently on v25.x — spreading a Promise yields no array items and Chrome launches with only "--my-flag". Always await: const baseArgs = await puppeteer.defaultArgs(); const args = [...baseArgs, '--my-flag'];
    costmediumin prodimmediate exceptionusers seeservice unavailablevisibilitysilent
    Sources[19][18]
  • trimCache · trimcache-unsupported-platform-error
    warning
    WhenHost platform is not one of the platforms @puppeteer/browsers recognizes (e.g. exotic ARM64 Linux distros, unusual containers)
    ThrowsPromise rejection with Error('The current platform is not supported.') OR Error from fs.rm on permission failures while pruning cache directories
    Required handlingCaller MUST wrap puppeteer.trimCache() in try-catch. Two distinct failure modes: (1) platform detection fails — common in minimal containers without /etc/os-release or on uncommon ARM variants; (2) cache directory traversal hits a permission error (running as unprivileged user against a cache populated by root, or NFS-mounted cache with stale handles). In Docker build pipelines, an unhandled rejection here kills the whole build with no useful log line. Pattern: try { await puppeteer.trimCache(); } catch (error) { console.warn('trimCache skipped:', error); }
    costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
    Sources[20]

Sources

Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.

Official documentation
Changelog & releases

Research notes

Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.

Sources: puppeteer

Package: puppeteer Contract Version: 1.0.0 Last Verified: 2026-02-26


Official Documentation

Primary API Documentation

Method-Specific Documentation


Error Handling Resources

Official Guides

Community Resources


Security & CVE Information

CVE Databases

Behavioral Security Issues


GitHub Issues (Error Handling)

Critical Issues Referenced in Contract

  1. #738 - Can't catch errors with .goto()
  2. #3709 - Page crashes when not calling Error catch
  3. #2269 - Closing browser throws error
  4. #2752 - How to close browser after error
  5. #4847 - How to close browser after Navigation Timeout
  6. #9317 - Navigation timeout crashes script
  7. #4502 - page.goto() does not throw on 404
  8. #10144 - ProtocolError: Target.createTarget timed out
  9. #11066 - Creating a new page in headless mode times out

Real-World Usage Analysis

Production Code Examples

Common Anti-Patterns Identified

  • 73% of code lacks try-catch around puppeteer.launch()
  • 67% of code has no timeout handling on page.goto()
  • 43% of code doesn't close browser in finally block
  • Official examples teach anti-patterns (6% have error handling)

Contract Design Rationale

ERROR Severity Functions

Functions marked as ERROR severity are those that:

  1. Cause process crashes when unhandled (Node.js v15+ default behavior)
  2. Are #1 production failure causes (navigation timeouts)
  3. Create resource leaks (zombie Chrome processes)

WARNING Severity Functions

Functions marked as WARNING severity are those that:

  1. Should be handled to prevent resource leaks
  2. Commonly fail in production but don't always crash
  3. Impact reliability but may have fallback strategies

Key Research Findings

  • 85% of real-world code lacks proper error handling
  • Navigation timeouts are the #1 cause of Puppeteer failures
  • Zombie processes accumulate without finally block cleanup
  • HTTP 404/500 do NOT throw in headless shell mode (critical gotcha)
  • Official examples are misleading - show zero error handling

Testing & Validation

Test Coverage

  • ✅ puppeteer.launch() error handling
  • ✅ page.goto() timeout handling
  • ✅ browser.close() in finally block
  • ✅ browser.newPage() error handling
  • ✅ page.waitForSelector() timeout handling
  • ✅ page.click() error handling

Test Fixtures Location

corpus/packages/puppeteer/fixtures/


Additional Resources

Docker/Container Issues

Performance & Memory


Maintenance Notes

Contract Verified: 2026-02-26 Research Phases: 1-4 completed CVE Search Date: 2026-02-26 Usage Analysis: AI-Collections + Official Examples + 9 GitHub issues

Next Review: 2026-08-26 (6 months)

Need a different package?
Request a profile