question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

INTERNAL ERROR: missing context with id = 2

See original GitHub issue

TLDR. I’m desperately hoping someone can help with this. I’ve been at it for 2 days and it’s driving me crazy. I’m working on creating a simplified repro case but I’m hoping someone might be able to point me in the right direction. It feels like puppeteer is possibly getting a bit confused about context when running in a highly parallel environment, but I’m probably wrong.

This problem occurs both locally running Docker and on CircleCI.

Steps to reproduce

 FAIL  __tests__/visual-regression/cta.test.js (79.643s)
  ● 99-visual-regression-cta-cta - mobile - ltr

    INTERNAL ERROR: missing context with id = 2

      at assert (node_modules/puppeteer/lib/helper.js:251:11)
      at FrameManager.createJSHandle (node_modules/puppeteer/lib/FrameManager.js:223:5)
      at ExecutionContext.evaluateHandle (node_modules/puppeteer/lib/ExecutionContext.js:89:17)

We an enormous visual regression test suite, a hundred or so prebuilt html files each containing a html component. We test each in 3 different viewports both right to left and left to right, so 6 visual regression tests per file using jest-image-snapshot. We have the tests broken down into a bunch of different files so jest is able to run them in parallel.

Tell us about your environment:

  • Puppeteer version: 1.5.1
  • Platform / OS version: circleci/node:8-browsers
  • Node.js version: 8
  • Jest: 22.4.3
  • Jest-image-snapshot: 2.4.0

Sample

Example runner

require('../_lib/visual-regression').performVisualRegression('foo/bar/');

Simplified visual-regression.js.

function performVisualRegression(dir, viewports = viewportSpecs.map((v) => v.id)) {
  const slugs = getSlugs(dir);

  for (const slug of slugs) {
    for (const viewport of viewportSpecs.filter((v) => viewports.includes(v.id))) {
      for (const direction of ['ltr', 'rtl']) {
        // test.concurrent
        test(`${slug} - ${viewport.id} - ${direction}`, performTest(slug, viewport, customSnapshotsDir, direction), 30000);
      }
    }
  }
}

function performTest(slug, viewport, customSnapshotsDir, direction = 'ltr') {
  const url = `${global.BASE_URL}/patterns/${slug}/${slug}.rendered.html`;

  return async() => {
    let page;

    try {
      page = await browser.newPage();
      await page.setCacheEnabled(false);
      await page.setViewport(viewport);

      const response = await page.goto(url, { timeout: 15000, waitUntil: ['load', 'networkidle2'] });
      expect(await response.ok()).toBe(true);

      await page.$eval('html', (div, dir) => div.setAttribute('dir', dir), direction);

      const elm = await page.$('body > *:not(script):not(style):not(link):not(meta)');
      expect(elm).not.toBeNull();

      await page.waitFor(250);

      const screenshot = await elm.screenshot();

      expect(screenshot).toBeTruthy();
      expect(screenshot instanceof Buffer).toBe(true);

      let snapshotId = `${name}~~${viewport.id}~~${direction}`;

      const config = Object.assign({}, defaultSnapshotConfig, { customSnapshotsDir, customSnapshotIdentifier: snapshotId });
      expect(screenshot).toMatchImageSnapshot(config);

    } finally {
      if (page) {
        await page.close();
      }
    }
  };
}

Jest environment.

const NodeEnvironment = require('jest-environment-node');
const puppeteer = require('puppeteer');

class PuppeteerEnvironment extends NodeEnvironment {
  constructor(config) {
    super(config);

    this.browser = puppeteer.launch({
      headless: true,
      dumpio: false,
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',
      ]
    });
  }

  async setup() {
    await super.setup();

    const browser = await this.browser;

    browser.on('targetcreated', async(target) => {
      if (target.type() !== 'page') {
        return;
      }

      const page = await target.page();

      page.evaluateOnNewDocument(() => {
        window.env = 'test';
      });

      page.on('domcontentloaded', async() => {
        await page.evaluate(async() => {
          window.env = 'test';

          // Stop videos from mucking up visual regression tests
          document.querySelectorAll('video').forEach((v) => {
            v.removeAttribute('autoplay');
            v.setAttribute('preload', 'auto');

            v.pause();
            v.currentTime = 0;
            v.load();
          });
        });
      });
    });

    this.global.BROWSER = browser;
  }

  async teardown() {
    await super.teardown();

    const b = await this.browser;
    await b.close();
    this.browser = null;
  }

  dispose() {

  }

  runScript(script) {
    return super.runScript(script);
  }
}

module.exports = PuppeteerEnvironment;

I should add we’ve also been having other extremely weird stuff going on. Left is the reference, middle is the diff, and right is what was produced during the test run.

Viewport not being honoured, completely the wrong size. image

Completely the wrong component image

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
JoelEinbindercommented, Jul 9, 2018

I can’t repro the error with the test suite you sent. But I think I know what is going on.

In your setup script, you run page.evaluate on domcontentloaded. Then when your test is done, you close the page. But you don’t await the page.evaluate before calling page.close. So the page closes before the evaluation finishes, and when the evaluation does finish, the page has already closed and we fail to return the result of the evaluation with this error.

0reactions
JoelEinbindercommented, Jul 11, 2018

It is pretty much always wrong to not await code being run on events. You have another race in this code, which might no be manifesting. On domcontentloaded you set window.env = 'test';. But you don’t wait for this eval to run before moving on with your test. An indefinite amount of time could pass between the domcontentloaded event firing in Chromium, the domcontentloaded event firing in node, and then running the code in Chromium again via your evaluate. In your setup function, it should look something like this:

await new Promise(x => page.once('domcontentloaded', x);
await page.evaluate(() => ...);
Read more comments on GitHub >

github_iconTop Results From Across the Web

INTERNAL ERROR: missing context with id = 2 #2811 - GitHub
This certainly is our bug. This error can happen if there's a race condition between certain devtools protocol events; however, I don't yet ......
Read more >
Resolve "GENERIC_INTERNAL_ERROR" when querying ...
To resolve this error, look for the column with the data type int, and then update the data type of this column from...
Read more >
flutter - ChromeProxyService: Failed to evaluate expression ...
I am getting errors are given below: + ChromeProxyService: Failed to evaluate expression 'handlePrimaryPointer':InternalError: No frame with ...
Read more >
Error handling - Apollo GraphQL Docs
A client sent the hash of a query string to execute via automatic persisted queries, but the server has disabled APQ. OPERATION_RESOLUTION_FAILURE. The...
Read more >
Job succeed, but uploading artifacts fails with 500 error - GitLab
I'm facing a similar issue on Gitlab EE 13.6.2-ee version where artifact upload fails intermittently with 500 errors. Any workaround available?
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found