diff --git a/packages/basic-crawler/src/internals/basic-crawler.ts b/packages/basic-crawler/src/internals/basic-crawler.ts index 74616eaf3c8d..f19053c84690 100644 --- a/packages/basic-crawler/src/internals/basic-crawler.ts +++ b/packages/basic-crawler/src/internals/basic-crawler.ts @@ -1152,7 +1152,9 @@ export class BasicCrawler { + return this._throwOnFailedLaunch(launchContext, error); + }); if (anonymizedProxyUrl) { browser.on('disconnected', async () => { @@ -108,7 +111,9 @@ export class PlaywrightPlugin extends BrowserPlugin { + return this._throwOnFailedLaunch(launchContext, error); + }); browserContext.once('close', () => { if (userDataDir.includes('apify-playwright-firefox-taac-')) { @@ -174,6 +179,22 @@ export class PlaywrightPlugin extends BrowserPlugin, cause: unknown): never { + let debugMessage = `Failed to launch browser.` + + `${launchContext.launchOptions?.executablePath + ? ` Check whether the provided executable path is correct: ${launchContext.launchOptions?.executablePath}.` : ''}`; + if (process.env.APIFY_IS_AT_HOME) { + debugMessage += ' Make sure your Dockerfile extends apify/actor-node-playwright-*` (with a correct browser name). Or install'; + } else { + debugMessage += ' Try installing'; + } + debugMessage += ' the required dependencies by running `npx playwright install --with-deps` (https://playwright.dev/docs/browsers).' + + ' The original error will be displayed at the bottom as the [cause].'; + throw new CriticalError(debugMessage, { + cause, + }); + } + protected _createController(): BrowserController[0], PlaywrightBrowser> { return new PlaywrightController(this); } diff --git a/packages/browser-pool/src/puppeteer/puppeteer-plugin.ts b/packages/browser-pool/src/puppeteer/puppeteer-plugin.ts index 5e0de0f1cbf5..8d011e615e28 100644 --- a/packages/browser-pool/src/puppeteer/puppeteer-plugin.ts +++ b/packages/browser-pool/src/puppeteer/puppeteer-plugin.ts @@ -1,3 +1,4 @@ +import { CriticalError } from '@crawlee/core'; import type { Dictionary } from '@crawlee/types'; import type Puppeteer from 'puppeteer'; import type * as PuppeteerTypes from 'puppeteer'; @@ -72,10 +73,22 @@ export class PuppeteerPlugin extends BrowserPlugin< await close(); }); } - } catch (error) { + } catch (error: any) { await close(); - - throw error; + let debugMessage = `Failed to launch browser.` + + `${launchContext.launchOptions?.executablePath + ? ` Check whether the provided executable path is correct: ${launchContext.launchOptions?.executablePath}.` : ''}`; + if (process.env.APIFY_IS_AT_HOME) { + debugMessage += ' Make sure your Dockerfile extends `apify/actor-node-puppeteer-chrome. Or install'; + } else { + debugMessage += ' Try installing'; + } + debugMessage += ` a browser, if it's missing, by running \`npx @puppeteer/browsers install chromium --path [path]\`` + + ` and pointing \`executablePath\` to the downloaded executable (https://pptr.dev/browsers-api).` + + ` The original error will be displayed at the bottom as the [cause].`; + throw new CriticalError(debugMessage, { + cause: error, + }); } } diff --git a/packages/core/src/autoscaling/autoscaled_pool.ts b/packages/core/src/autoscaling/autoscaled_pool.ts index 8e1c601f6f02..376fdc992c86 100644 --- a/packages/core/src/autoscaling/autoscaled_pool.ts +++ b/packages/core/src/autoscaling/autoscaled_pool.ts @@ -9,6 +9,7 @@ import { Snapshotter } from './snapshotter'; import type { SystemInfo, SystemStatusOptions } from './system_status'; import { SystemStatus } from './system_status'; import { Configuration } from '../configuration'; +import { CriticalError } from '../errors'; import { log as defaultLog } from '../log'; export interface AutoscaledPoolOptions { @@ -551,7 +552,12 @@ export class AutoscaledPool { // We might have already rejected this promise. if (this.reject) { // No need to log all concurrent errors. - this.log.exception(err, 'runTaskFunction failed.'); + if ( + // avoid reprinting the same critical error multiple times, as it will be printed by Nodejs at the end anyway + !(e instanceof CriticalError) + ) { + this.log.exception(err, 'runTaskFunction failed.'); + } this.reject(err); } } diff --git a/packages/core/src/errors.ts b/packages/core/src/errors.ts index f8a0e1499f4c..3e55610caf62 100644 --- a/packages/core/src/errors.ts +++ b/packages/core/src/errors.ts @@ -5,6 +5,7 @@ export class NonRetryableError extends Error {} /** * Errors of `CriticalError` type will shut down the whole crawler. + * Error handlers catching CriticalError should avoid logging it, as it will be logged by Node.js itself at the end */ export class CriticalError extends NonRetryableError {} diff --git a/yarn.lock b/yarn.lock index 56d44b1ebce1..97c8de16bf0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -761,6 +761,7 @@ __metadata: dependencies: "@apify/log": ^2.4.0 "@apify/timeout": ^0.3.0 + "@crawlee/core": 3.5.2 "@crawlee/types": 3.5.2 fingerprint-generator: ^2.0.6 fingerprint-injector: ^2.0.5