Puppeteer errors, explained one by one
Last verified
Puppeteer surfaces failures as JavaScript errors thrown from the call that failed. Three classes matter: TimeoutError for anything that waited too long (navigations, waitForSelector, locators), ProtocolError for failures reported by the Chrome DevTools Protocol, and plain Error for everything else, including launch failures and network errors from page.goto(). You can check for timeouts with err instanceof TimeoutError, importing TimeoutError from puppeteer.
Read Puppeteer errors in two layers. The message names the symptom; the context tells you the cause. For launch failures, the stderr block that Puppeteer copies from Chrome is where the real reason lives. For protocol errors, the method in parentheses, such as Target.setDiscoverTargets or Runtime.callFunctionOn, tells you what Puppeteer was doing when the connection went away. In current versions, wait errors carry their timeout detail in err.cause.
The errors below fall into a few families: navigation (slow loads, DNS failures, aborted downloads), selectors and elements (nothing matched, hidden or detached nodes), frames and execution contexts that disappear during navigation, connection and session errors when a page or browser closes, and installation problems where Chrome is missing or cannot start. Each entry quotes the literal message, explains what it does and does not mean, and lists fixes in the order worth trying. For a side-by-side comparison with Playwright and Selenium, see Playwright vs Selenium vs Puppeteer.
Official reference: Puppeteer docs - Troubleshooting
How to read a Puppeteer error
A launch failure: the headline is generic, the copied stderr names the cause.
Error: Failed to launch the browser process: Code: 127
stderr:
/home/user/.cache/puppeteer/chrome/linux-142.0.7444.59/chrome-linux64/chrome: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory
TROUBLESHOOTING: https://pptr.dev/troubleshootingA protocol error: the method in parentheses shows which DevTools command was pending when the target closed.
ProtocolError: Protocol error (Target.setDiscoverTargets): Target closedAll 15 messages
Jump to: Navigation & network (4) · Selectors & waiting (2) · Element handles & clicking (3) · Frames (2) · Protocol, session & connection (2) · Installation & launching Chrome (2)
Navigation & network
| Message |
|---|
Navigation timeout of 30000 ms exceededTimeoutError: Navigation timeout of 30000 ms exceeded |
Execution context was destroyed, most likely because of a navigationError: Execution context was destroyed, most likely because of a navigation. |
net::ERR_NAME_NOT_RESOLVED at <url>Error: net::ERR_NAME_NOT_RESOLVED at https://exmaple.com/ |
net::ERR_ABORTED at <url>Error: net::ERR_ABORTED at https://example.com/report.pdf |
Selectors & waiting
| Message |
|---|
TimeoutError: Waiting for selector failedTimeoutError: Waiting for selector `.results` failed
[cause]: TimeoutError: Waiting failed: 30000ms exceeded |
No element found for selectorError: No element found for selector: #submit |
Element handles & clicking
| Message |
|---|
Node is either not visible or not an HTMLElementError: Node is either not visible or not an HTMLElement |
Node is either not clickable or not an ElementError: Node is either not clickable or not an Element |
Node is detached from documentError: Node is detached from document |
Frames
| Message |
|---|
Attempted to use detached FrameError: Attempted to use detached Frame 'A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6'. |
Navigating frame was detachedError: Navigating frame was detached |
Protocol, session & connection
| Message |
|---|
Protocol error (Target.setDiscoverTargets): Target closedProtocolError: Protocol error (Target.setDiscoverTargets): Target closed |
Session closed. Most likely the page has been closed.Error: Protocol error (Runtime.callFunctionOn): Session closed. Most likely the page has been closed. |
Installation & launching Chrome
| Message |
|---|
Could not find Chrome (ver. X). This can occur if either...Error: Could not find Chrome (ver. 142.0.7444.59). This can occur if either
1. you did not perform an installation before running the… |
Failed to launch the browser processError: Failed to launch the browser process: Code: 127
stderr:… |
Definitions
- PuppeteerPuppeteer is Google's open-source Node.js library for controlling Chrome and Firefox. It drives Chrome over th
- Chrome DevTools Protocol (CDP)The Chrome DevTools Protocol (CDP) is the JSON-over-WebSocket interface Chrome exposes for inspecting and cont
- CSS SelectorA CSS selector is a pattern used to identify and target specific HTML elements on a web page, widely used in b
- Headless ChromeHeadless Chrome is Google Chrome running without a visible window. It renders pages and runs JavaScript like n
- IframeAn iframe (inline frame) is an HTML element that embeds a separate web page within a parent page, creating an
- Web ElementA web element is any individual component rendered on a web page — buttons, links, input fields, images, text
Puppeteer guides, limits and tools
Other error directories
- Cloudflare error pages errors16 messages
- Google Apps Script errors16 messages
- Google Sheets IMPORT functions errors15 messages
- HTTP errors in web scraping and automation errors15 messages
- Make (formerly Integromat) errors9 messages
- n8n errors11 messages
- Playwright errors16 messages
- Selenium WebDriver errors14 messages
- Zapier errors8 messages
Frequently asked questions
What is Puppeteer's default timeout?
30 seconds for navigations and for waits such as waitForSelector, waitForFunction and locator actions. Change it globally with page.setDefaultTimeout(ms) and page.setDefaultNavigationTimeout(ms), or per call with the timeout option. Passing 0 disables the timeout, which is rarely a good idea in production because a stuck page will then hang the script forever.
How do I catch a timeout specifically?
Import TimeoutError from puppeteer and check err instanceof TimeoutError in your catch block. That separates slow pages, which may be worth retrying, from real failures such as missing selectors, DNS errors or a crashed browser. In current versions, inspect err.cause on wait errors for the underlying timeout detail.
Should I use waitUntil networkidle0?
Only for pages that truly go quiet. networkidle0 waits until there have been no network connections for 500 ms, which never happens on sites with analytics beacons, websockets or polling, so navigations time out. Navigating with domcontentloaded and then waiting for a specific selector is faster and more reliable for most scraping and testing.
What is the Locator API and does it help with these errors?
page.locator(selector) returns a locator whose actions, such as click and fill, wait for the element to be attached, visible, enabled and stable before acting, and re-query the page each time. It avoids No element found for selector, most detached-node errors and many not-clickable errors that come from acting on elements too early.
Why does Puppeteer work locally but fail in Docker?
Containers usually lack Chrome's system libraries, run as root, and have only 64 MB of /dev/shm. Those produce Failed to launch the browser process and Target closed errors. Use an image built for headless Chrome, run as a non-root user, and add --shm-size=1gb or the --disable-dev-shm-usage flag.
Is it safe to launch with --no-sandbox?
It disables Chrome's process sandbox, which protects the host from malicious page content. It is acceptable when you control the pages being loaded and the container is already isolated, but it is risky for crawling arbitrary sites. Running Chrome as a non-root user usually makes the flag unnecessary.
Where does Puppeteer install Chrome?
Into a cache directory, ~/.cache/puppeteer by default, during npm install. Each Puppeteer version expects one specific Chrome for Testing build. You can change the location with a .puppeteerrc.cjs file or the PUPPETEER_CACHE_DIR environment variable, and install manually with npx puppeteer browsers install chrome.
Why do my element handles keep going stale?
An ElementHandle points to one DOM node. Modern frameworks replace nodes when they re-render, and navigations destroy them entirely, so stored handles become detached. Query elements just before using them, extract plain values instead of passing handles around, and prefer locators, which re-resolve the selector on every action.
Run browser automation you can watch and take over
Autonoly runs each job in a real cloud Chromium browser driven by Playwright. Timeouts and detached elements still happen; the difference is that you can watch the run live, see the step that failed, and take control of the browser to finish it.