Fix an unhandled rejection where the failing promise is created or invoked: await it inside a try/catch, attach a meaningful .catch(), or return it to a caller that handles it. Then identify whether the error came from Node.js code, JavaScript running in the page, or Puppeteer’s browser protocol. A process-level rejection listener can help you observe a failure, but it does not repair the operation or make it safe to continue.
What an unhandled rejection means in Node.js
An unhandled rejection is a rejected promise for which no rejection handler is attached within a turn of the event loop. It is a Node.js runtime condition, not a special Puppeteer exception. Node.js v26.10.0 documents that it emits unhandledRejection with the rejection reason and promise; if a handler is attached later, Node can emit rejectionHandled. See the Node.js Process API documentation.
The missing handler may be several steps away from the Puppeteer call that appears in the log. A .then() callback can throw, producing a rejected promise for the chain returned by .then(). If that returned promise is neither returned to its caller nor caught, the original operation may look handled while the new rejection is not.
Find the promise that lost its error path
- Keep the full reason and stack. Do not log only a generic message or discard the rejection reason. The process event provides both the reason and the promise, which can help identify the unowned chain.
- Trace promise-producing calls. Review Puppeteer calls such as
page.goto(),page.click()andbrowser.newPage(), plus every.then()orasynccallback that starts work. Check timers and event listeners too: work started there is not automatically awaited by the code that registered the callback. - Give each operation a clear owner. Either await it in an async function that catches failure, return it so the caller can await or catch it, or attach a local
.catch()with a deliberate response. Avoid starting asynchronous work and dropping its promise. - Identify the execution context. A Node-side rejection, a page JavaScript error, browser console output, and a stalled browser-protocol operation are different signals. Use the matching diagnostic path below.
Catch failures at the workflow boundary
For a sequence of Puppeteer actions, a useful pattern is to let the async workflow reject, catch that top-level promise, and set a failure exit code. Keep cleanup in finally so the browser is closed whether navigation succeeds or fails.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
const puppeteer = require('puppeteer');
async function run() {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com');
// Await the rest of the Puppeteer operations here.
} finally {
await browser.close();
}
}
run().catch(error => {
console.error('Puppeteer task failed:', error);
process.exitCode = 1;
});
This sample makes the workflow’s rejection visible to its caller and reports it at the top-level boundary. Choose a different error policy if the application needs one, but do not silently swallow failures. Also account for cleanup failures: browser.close() can itself reject, potentially obscuring an earlier failure. If that matters to your application, handle cleanup errors deliberately while preserving the original error context.
Catch a single operation locally
async function openPage(page, url) {
try {
await page.goto(url);
} catch (error) {
console.error(`Navigation failed for ${url}:`, error);
throw error;
}
}
Rethrowing preserves the failure for the caller instead of making the function appear successful. If recovery is appropriate—for example, a specific optional operation can be skipped—handle that case explicitly and document what the application will do next.
Return promise chains instead of detaching them
Each chain call produces a promise that can reject. Return nested work so the upstream caller owns it, or handle the chain where it is created:
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
function readTitle(page) {
return page.title().then(title => {
return saveTitle(title); // The returned promise remains part of the chain.
});
}
readTitle(page).catch(error => {
console.error('Could not read or save the title:', error);
process.exitCode = 1;
});
If the callback throws, the promise produced by .then() rejects. Catching an unrelated earlier promise will not handle that later chain. Node’s promise rejection documentation describes this behavior and the use of .catch() to handle rejection.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Handle asynchronous callbacks and event listeners
An event emitter generally does not await a promise returned by an async listener. If the listener starts asynchronous Puppeteer work, put a rejection handler inside that listener or pass its work to a function that owns the resulting promise. Avoid an unobserved async callback such as page.on('load', async () => { await doWork(); }) unless the listener explicitly catches failures.
page.on('load', () => {
void doWork().catch(error => {
console.error('Work started by load event failed:', error);
});
});
Here, void makes the intentional detachment visible; the attached .catch() is still what handles failure. Alternatively, store or return the promise through an application-level mechanism that awaits it. Choose based on whether the event callback’s caller can actually observe and await that promise.
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
Request interception has an additional race condition
When request interception is enabled, a request stalls until it is continued, answered, or aborted. Puppeteer’s request interception guide for version 25.12.0 documents returning a promise from a handler so Puppeteer can await its work. If another listener can resolve a request while your handler is awaiting, check request.isInterceptResolutionHandled() again immediately before calling abort(), continue(), or respond(). Keep the state check and resolution call together synchronously.
page.on('request', request => {
return (async () => {
try {
const shouldBlock = await checkRequest(request);
// Another handler may have resolved it during the await.
if (request.isInterceptResolutionHandled()) return;
if (shouldBlock) {
await request.abort();
} else {
await request.continue();
}
} catch (error) {
console.error('Request handler failed:', error);
if (!request.isInterceptResolutionHandled()) {
await request.continue();
}
}
})();
});
Adapt the recovery branch to your interception policy; continuing a request is not appropriate in every application. A rejected promise from the handler’s own work and an attempt to resolve an already-resolved request are separate problems. The state recheck addresses the race; it is not generic rejection handling. Verify details against the Puppeteer version in your lockfile. See the Puppeteer request interception guide.
Recommended Free Tools
Distinguish Node errors from page errors
Puppeteer separates Node “server code” from browser “client code.” A failure in page JavaScript does not necessarily become a Node promise rejection, and page console output is not automatically printed in the Node process. Puppeteer’s debugging guide and PageEvents API document signals for investigating these contexts.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
| Signal | What it indicates | Useful next step |
|---|---|---|
Node unhandledRejection |
A rejected Node-side promise did not gain a handler within an event-loop turn. | Inspect the reason and stack; trace the promise chain and add a handler at its owner. |
page.on('console', ...) |
Console messages emitted by JavaScript in the page. | Relay the messages to Node logs so page-side output is visible. |
page.on('pageerror', ...) |
An error thrown by page JavaScript, reported separately from a Node process rejection. | Inspect the event’s error payload and debug the page context. |
| Pending protocol errors | An asynchronous Puppeteer call may be stuck rather than rejected. | Inspect browser.debugInfo.pendingProtocolErrors as described in Puppeteer’s debugging guide. |
page.on('console', message => {
console.log('PAGE CONSOLE:', message.type(), message.text());
});
page.on('pageerror', error => {
console.error('PAGE ERROR:', error);
});
Use global rejection events for observation, not recovery
A process-level listener is useful for diagnostics or monitoring, especially while finding missed handlers. It is not a substitute for handling the specific promise, and logging the error does not make the failed Puppeteer operation succeed.
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled rejection:', reason);
// Use the promise only for diagnostics if needed; repair its owner.
});
Node’s behavior for an unhandled rejection can be affected by the --unhandled-rejections option. Node documents that an unhandled rejection may be raised as an uncaught exception. Its guidance warns: “It is not safe to resume normal operation after ‘uncaughtException’.” Treat that hook as a last-resort shutdown or reporting boundary, not a way to keep automation running after arbitrary failures. See the Node.js uncaughtException documentation.
Debug the cause when the rejection is caught but unexplained
- Node-side calls: Use Node’s inspector to debug the code that invokes Puppeteer.
- Page-side JavaScript: Enable browser DevTools and use a
debuggerstatement in the client code. - Puppeteer protocol traffic: Set
NODE_DEBUG="puppeteer:*"to log protocol traffic. This aids diagnosis; it does not repair a missing handler. - Calls that do not resolve: Inspect
browser.debugInfo.pendingProtocolErrorsusing the approach in Puppeteer’s debugging documentation.
The cited Puppeteer debugging guide is version 25.12.0, while the PageEvents API reference is version 25.11.0; event and interception details can vary across releases. Check the documentation matching the version installed by your project.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
Troubleshoot common Puppeteer rejection patterns
| Symptom | Likely cause | Fix |
|---|---|---|
The script logs an unhandled rejection after a .then(). |
A callback threw or returned a rejected promise, and the new chain was not handled. | Return nested asynchronous work and attach .catch() to the resulting chain, or await it within a surrounding try/catch. |
| An async event callback fails but the main function’s catch does not run. | The event emitter did not await the callback’s promise. | Catch within the listener or pass the promise to a mechanism that explicitly awaits it. |
| A page error does not appear in Node’s rejection logs. | The failure occurred in browser page JavaScript, not in the Node process. | Listen for pageerror; relay page console events separately. |
| An intercepted request throws while being continued, aborted, or answered. | Another handler may have resolved the request while this handler awaited. | Recheck isInterceptResolutionHandled() after the await and just before resolving it. |
| The operation appears stuck and no rejection arrives. | The protocol call may be pending instead of rejected. | Use Puppeteer’s protocol debugging options and inspect pending protocol errors. |
| A global listener prints the error, but the task still fails. | The listener observes the rejection without handling the operation’s application-level outcome. | Repair the promise ownership path and decide explicitly whether to recover, fail the task, or shut down. |
Or skip the browser setup
If your task is simply to capture a website screenshot, ScreenshotNeo provides a one-request alternative to managing a Puppeteer browser locally. Its API accepts a URL and returns a screenshot or PDF. The API also accepts familiar screenshot-API parameter names, which can make switching easier.
curl -G "https://api.screenshotneo.com/v1/shot"
-d access_key=YOUR_API_KEY
--data-urlencode url=https://example.com
-o shot.webp
See the ScreenshotNeo API documentation for parameters and response details. ScreenshotNeo says it removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Responses include X-Page-Verdict and X-Billed headers. Its MCP server offers take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Visit ScreenshotNeo or sign up free for 1,000 screenshots a month, with no card required.
Frequently Asked Questions
Does catching an unhandled rejection mean the Puppeteer operation succeeded?
No. A handler observes or responds to the failure; it does not turn the failed operation into a successful one. Recovery must be explicit and appropriate to that operation.
Should I use `uncaughtException` to keep a Puppeteer script running?
No. Node.js warns that resuming normal operation after an uncaught exception is unsafe. Use it only as a last-resort reporting or shutdown boundary.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

