7

I am new to Puppeteer and Node and I get this error when trying to execute the following code:

'use strict';

const puppeteer = require('puppeteer');
const evalLib = require('./oaa_a11y_evaluation.js');

function evaluateRules() {
  var ruleset = OpenAjax.a11y.RulesetManager.getRuleset("ARIA_STRICT");
  var evaluator_factory = OpenAjax.a11y.EvaluatorFactory.newInstance();
  evaluator_factory.setParameter('ruleset', ruleset);
  evaluator_factory.setFeature('eventProcessing', 'fae-util');
  evaluator_factory.setFeature('groups', 7);
  var evaluator = evaluator_factory.newEvaluator();
  var evaluation = evaluator.evaluate(window.document, document.title, document.location.href);
  // var out = evaluation.toJSON(true);
  return;
}

(async() => {
  const browser = await puppeteer.launch();
  var page = await browser.newPage();
  await page.goto('http://mihirkumar.com/', {waitUntil: 'load'});
  page.evaluate(evaluateRules);
  await browser.close();
})();

Here's the error message in full detail:

(node:27876) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.
at Promise (C:\Users\Mihir\fae\node_modules\puppeteer\lib\Connection.js:200:56)
at new Promise (<anonymous>)
at CDPSession.send (C:\Users\Mihir\fae\node_modules\puppeteer\lib\Connection.js:199:12)
at ExecutionContext.evaluateHandle (C:\Users\Mihir\fae\node_modules\puppeteer\lib\ExecutionContext.js:79:75)
at ExecutionContext.evaluate (C:\Users\Mihir\fae\node_modules\puppeteer\lib\ExecutionContext.js:46:31)
at Frame.evaluate (C:\Users\Mihir\fae\node_modules\puppeteer\lib\FrameManager.js:326:20)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
(node:27876) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:27876) [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.

Other examples from https://github.com/GoogleChromeLabs/puppeteer-examples run perfectly fine so I don't believe I need to use the fixes mentioned here. Thanks for the help.

Mihir Kumar
  • 191
  • 1
  • 2
  • 11
  • Is your problem that you don't know how to handle that unhandled rejection, or that you don't know why you get that protocol error? – Bergi Jun 01 '18 at 14:13
  • I don't know how to handle the rejection and I don't know why it's occurring/what I'm doing wrong to cause it. Apart from the obvious message 'Target closed' I don't know much more. – Mihir Kumar Jun 01 '18 at 14:16
  • Handle rejections with `try`/`catch` around the `await`. Though in this case there's no much you can do other than print the error message and fail your test. – Bergi Jun 01 '18 at 14:17
  • Putting a try catch around the awaits isn't making the problem go away. – Mihir Kumar Jun 01 '18 at 14:22
  • Yes, it's just making the "unhandled rejection warning" go away. I have no idea what the problem that causes the protocol error could be - but if that's what you want to know, you should [edit] your question and provide a more appropriate title. – Bergi Jun 01 '18 at 14:25
  • If you wrap the `await` expressions in a `try/catch`-block, and add an `await page.close()` *before* the `await browser.close()`, do you get a different result? – Sven Jun 01 '18 at 14:30
  • 1
    It's also worth mentioning that `page.evaluate()` returns a promise, so you should `await` it. At the moment, you are not waiting for it to finish, and are immediately executing `browser.close()` before `page.evaluate()` has finished. – Sven Jun 01 '18 at 14:34
  • See also [Puppeteer - Protocol error (Page.navigate): Target closed](https://stackoverflow.com/questions/51629151/puppeteer-protocol-error-page-navigate-target-closed/68231165#68231165) – ggorlen Jul 02 '21 at 21:05

3 Answers3

5

As Sven mentioned in the comments, you should use await on every page function that returns a promise (that's almost all of them) before closing the browser.

Try this:

'use strict';

const puppeteer = require('puppeteer');
const evalLib = require('./oaa_a11y_evaluation.js');

async function evaluateRules() {
  var ruleset = OpenAjax.a11y.RulesetManager.getRuleset("ARIA_STRICT");
  var evaluator_factory = OpenAjax.a11y.EvaluatorFactory.newInstance();
  evaluator_factory.setParameter('ruleset', ruleset);
  evaluator_factory.setFeature('eventProcessing', 'fae-util');
  evaluator_factory.setFeature('groups', 7);
  var evaluator = evaluator_factory.newEvaluator();
  var evaluation = evaluator.evaluate(window.document, document.title, document.location.href);
  // var out = evaluation.toJSON(true);
  return;
}

(async() => {
  const browser = await puppeteer.launch();
  var page = await browser.newPage();
  await page.goto('http://mihirkumar.com/', {waitUntil: 'load'});
  await page.evaluate(evaluateRules); // <-- await here
  await browser.close();
})();
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Nicolás A.
  • 523
  • 4
  • 10
1

Thanks for the responses. Making the function async is definitely a change for the better. My problem was that I wasn't injecting the OpenAjax javascript libraries into the loaded page. Once I did that with puppeteer's page.addScriptTag function things worked just fine.

Mihir Kumar
  • 191
  • 1
  • 2
  • 11
0

If U are using jest just add "exitOnPageError: false" on

module.exports = {
  server: {
    command: "PORT=3005 BROWSER=none react-scripts start",
    port: 3005,
    launchTimeout: 30000,
  },
  launch: {
    headless: process.env.HEADLESS !== "false",
    devtools: true,
  },
  exitOnPageError: false
};