Reputation: 79178
Every now and then a page will be finicky and error out with this:
UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Session closed. Most likely the page has been closed.
at CDPSession.send (/Users/lancepollard/start/lancejpollard/data/node_modules/puppeteer/lib/cjs/puppeteer/common/Connection.js:195:35)
at ExecutionContext._evaluateInternal (/Users/lancepollard/start/lancejpollard/data/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:200:50)
at ExecutionContext.evaluate (/Users/lancepollard/start/lancejpollard/data/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:106:27)
at DOMWorld.evaluate (/Users/lancepollard/start/lancejpollard/data/node_modules/puppeteer/lib/cjs/puppeteer/common/DOMWorld.js:79:24)
at emitUnhandledRejectionWarning (internal/process/promises.js:149:15)
at processPromiseRejections (internal/process/promises.js:211:11)
at processTicksAndRejections (internal/process/task_queues.js:98:32)
(node:38857) Error: Protocol error (Runtime.callFunctionOn): Session closed. Most likely the page has been closed.
at CDPSession.send (/Users/lancepollard/start/lancejpollard/data/node_modules/puppeteer/lib/cjs/puppeteer/common/Connection.js:195:35)
at ExecutionContext._evaluateInternal (/Users/lancepollard/start/lancejpollard/data/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:200:50)
at ExecutionContext.evaluate (/Users/lancepollard/start/lancejpollard/data/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:106:27)
at DOMWorld.evaluate (/Users/lancepollard/start/lancejpollard/data/node_modules/puppeteer/lib/cjs/puppeteer/common/DOMWorld.js:79:24)
(node:38857) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Why is this happening and how do you fix it?
Upvotes: 3
Views: 17092
Reputation: 6336
I don't know why you get this error, you should probably add your code to the question.
For me, this is how I handle crush browser / page errors:
async initiate() {
this.pageOptions = {
waitUntil: 'networkidle2',
timeout: 60000
};
puppeteerExtra.use(pluginStealth());
this.browser = await puppeteerExtra.launch({ headless: false });
const browserWSEndpoint = await this.browser.wsEndpoint();
puppeteerExtra.connect({ browserWSEndpoint: browserWSEndpoint });
this.page = await this.browser.newPage();
await this.page.setRequestInterception(true);
this.page.on('request', (request) => {
if (['image', 'stylesheet', 'font', 'script'].indexOf(request.resourceType()) !== -1) {
request.abort();
} else {
request.continue();
}
});
this.page.on('dialog', async dialog => {
await dialog.dismiss();
});
}
wait = (ms) => new Promise(resolve => setTimeout(resolve, ms))
async restart() {
await this.close();
await this.wait(1000);
this.initiate();
}
async close() {
if (this.browser) {
await this.page.close();
await this.browser.close();
this.browser = null;
this.page = null;
this.pageOptions = null;
}
}
And the crawl process:
crawl(link, userAgent) {
return new Promise(async (resolve, reject) => {
if (reject) { }
// Limit the runtime of this function in case of stuck URL crawling process.
setTimeout(async () => {
await this.restart();
resolve(null);
return;
}, 60000);
if (!userAgent) {
userAgent = crawlUtils.getRandomUserAgent();
}
const crawlResults = { isValidPage: true, pageSource: null };
if (!this.page) {
await this.wait(1000);
resolve(null);
return;
}
try {
await this.page.setUserAgent(userAgent);
await this.page.goto(link, this.pageOptions);
await this.page.waitForFunction(this.waitForFunction);
crawlResults.pageSource = await this.page.content();
}
catch (error) {
crawlResults.isValidPage = false;
}
if (this.isLinkCrawlTest) {
await this.close();
}
resolve(crawlResults);
});
}
Upvotes: 4