How to catch timeout exceptions in Puppeteer's waitForSelector method

I’m working with Puppeteer and running into an issue with error handling. When I click a button to submit and expect results, it works fine if the input is correct. However, when the input is incorrect, the results do not appear, causing my script to fail.

await page.click('button[class="button form-button rs-gcbalance-btn"]')

await page.waitForSelector('div[class="small-4 large-4 rs-gcbalance-result-num-col"]').catch(error => console.log(error))

await page.evaluate((card) => {
    console.log(card + " - " + document.querySelectorAll('div[class="small-4 large-4 rs-gcbalance-result-num-col"]')[1].querySelector('span').innerHTML)
}, card)

The issue occurs when invalid data is provided. Since the page doesn’t navigate and no error elements are displayed, my waitForSelector ends up timing out after 30 seconds, which results in a crash of the entire program.

TimeoutError: waiting for selector failed: timeout 30000ms exceeded

I need to find a way to correctly handle this timeout error to manage invalid inputs without causing the program to crash. It would be great to try a different approach or display an appropriate message instead.

The problem is you’re not accounting for the fact that your selector might never show up. Don’t wait indefinitely for an element that may not exist - use Promise.race() to handle multiple outcomes at once. Race your waitForSelector against other selectors that could indicate errors or completion.

const result = await Promise.race([
    page.waitForSelector('div[class="small-4 large-4 rs-gcbalance-result-num-col"]', {timeout: 10000}),
    page.waitForSelector('.error-message', {timeout: 10000}).then(() => 'error'),
    new Promise(resolve => setTimeout(() => resolve('timeout'), 8000))
]);

This gives you control over each scenario. You can branch your logic based on whether you got the element you wanted, an error, or a timeout. Makes your automation way more reliable.

That timeout error is actually normal when you’re dealing with elements that might not show up. Don’t just rely on catch blocks - use waitForSelector with a shorter timeout and better error handling instead. Set a custom timeout and check if the element exists before running your evaluation. Try await page.waitForSelector('your-selector', {timeout: 5000}).catch(() => null) - this returns null on timeout instead of throwing an exception. After waiting, use page.$('your-selector') to verify the selector actually exists before extracting data. This lets you tell the difference between valid results and errors, so your script keeps running and handles invalid inputs properly.