React: "Missing React element for debugID" warning when testing components with Jest

Created on 10 Jul 2016  ·  62Comments  ·  Source: facebook/react

Do you want to request a _feature_ or report a _bug_?

Report a bug.

What is the current behavior?

When testing components, Warning: ReactComponentTreeDevtool: Missing React element for debugID 1 when building stack is shown when calling TestUtils.renderIntoDocument.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/reactjs/69z2wepo/).

https://github.com/angusfretwell/reproduce-debugid-warning (npm install && npm test).

What is the expected behavior?

According to #7187 this is an internal warning and shouldn't be displayed.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

I didn't receive this warning on 15.2.0.

Bug

Most helpful comment

Let’s keep it open until either fix gets in.

All 62 comments

Could this be some sort of a Jest issue (related to mocking?).
In your example, if I put a log in the top level scope of ReactComponentTreeDevtool.js, I see it twice.

screen shot 2016-07-10 at 11 54 25

screen shot 2016-07-10 at 11 55 05

I’m not sure if this is normal.

I can also “fix” the issue by moving requires inside the test:

jest.unmock('../../components/HelloWorld');

describe('HelloWorld', () => {
  it('displays the message', () => {
    var React = require('react');
    var ReactDOM = require('react-dom');
    var TestUtils = require('react-addons-test-utils');
    var HelloWorld = require('../../components/HelloWorld').default;

    const helloWorld = TestUtils.renderIntoDocument(<div><HelloWorld /></div>);
    const helloWorldNode = ReactDOM.findDOMNode(helloWorld);
    expect(helloWorldNode.textContent).toEqual('Hello World');
  });
});

I would advise you to file an issue with Jest. It shouldn’t be executing our modules twice.

Thanks for looking into this @gaearon, I will file an issue with Jest.

Reopening this as this is not a Jest issue. Downgrading React to 15.2.0 makes this warning go away in @angusfretwell's example. @angusfretwell thanks for providing a repo!

@gaearon can you look into this from the React side?

Hmm, I don't know enough about Jest to solve this in React. The only related change I can think of is that I inlined some requires to this module inside DEV blocks so that it doesn't get bundled to production. Does this cause Jest to execute it twice? Even though it worked before, I can't quite see how module being executed twice can be valid behavior. It doesn't happen in Node or in the browser and CommonJS does not allow this to my knowledge so I can't quite see yet how this can be React's issue.

(To clarify, yes, I know it's new in React 15.2.1. But it doesn't mean this is a React issue. It just looks like we hit an edge case in Jest that we didn't hit before. But I can try bisecting this if it helps.)

Jest resets the module registry before each call to it, so it is quite possible that people will end up with two copies of React if they aren't careful. Can you point me to the change in React since the last release?

Wow, I thought resetting is always explicit.
Then it is probably caused by https://github.com/facebook/react/pull/7188.
As you can see I had to doctor a few tests to make it pass but I thought those were caused by explicit resetModuleRegistry calls.

I still don't quite understand what is happening. Are lazy requires an unsupported pattern?

Oh, I see what is happening here now.

Here is how Jest works in open source:

  • We call jest.resetModuleRegistry() implicitly in every beforeEach call. When doing require('React') (or import) on the top-level and then require('React') inside of a call to it), they will be fresh copies both times. I suspect the debug module is freshly required from an old version of React which will then go and require new versions of modules it requires itself.

At Facebook here is how Jest works:

  • We explicitly call jest.resetModuleRegistry() in beforeEach. Not every test does this, but every test should and I've been hoping to turn the open source behavior on internally as well.
  • We use top-level requires _but_ we inline them. const React = require('React') will be removed and inlined into the code. Together with the module registry reset, this works pretty well and every call to it is completely isolated. Previously, the way we required modules in our tests internally was always quite the mess.

What we do at FB is what I'd recommend most people to do however people in open source have decided they want to use ES2015 imports, even in tests and there is not much I can do to stop them. That way they might end up with this confused state.

Jest sets the NODE_ENV to test – could we leverage this in React?

OK, I think I understand it now.

Seems like we could force those inline requires at the top of the file when NODE_ENV is test. We could then remove this hack when we start using Rollup and no longer need inline requires.

This will either be fixed by #7245 or #7178, depending on which goes first.
Thank you very much for a good repro case.

Thanks @gaearon!

Let’s keep it open until either fix gets in.

Anyway to quiet the warnings in the mean time? I have about 5000 of these warnings in my suite which makes it a bit hard to look at the test output.

As a super temporary fix you can put require('react/lib/ReactComponentTreeDevtool'); at the top level in your tests. I think this should fix the issue. Be sure to remove it when the next version is out 😄 . And only do this in tests.

Thanks for the suggestion :) . FWIW, it doesn't seem to have helped much.

In the mean time we're just dumping STDOUT to a file and inspecting that. Works quite well since the warnings are dumped to STDERR (for anyone with the same problem).

Along the same lines, you could also do something like npm run test 2>/dev/null if you are in a unix environment.

Face. Palm. Apparently I need more coffee.

Routing ERR to /dev/null works perfectly, as it should. Thanks again.

Also jest --silent will silence console messages.

@gaearon

you can put require('react/lib/ReactComponentTreeDevtool'); at the top level in your tests.

It doesn't work for me. I added this line at the top of all test files. I am still getting the same error.

I am using cmder/powershell on Windows. It look like there are two types of warnings. Ones are in white and another are in red. Please look at the screenshot below.

image

If I run "npm test > $null" then it doesn't show the error and the warning messages which are in red color anymore.

I'm also running in to this issue with Karma. Running the latest version (15.2.1). The proposed temporary workaround/fix with requiring the ReactComponentTreeDevtool didn't work either.

The fix will be out in 15.3.0 which will soon be released.

Also, 15.3.0 RCs are on npm so you can try using them.
https://github.com/facebook/react/issues/7220#issuecomment-234367952

@gaearon I test on official release 15.3.0. The warning was gone. Thanks for hard work. 💯

Great, thanks for verifying!

@jessy1092 What versions are you running?

I'm still seeing multiple instances of
ERROR: 'Warning: ReactComponentTreeDevtool: Missing React element for debugID 17 when building stack'

react 15.3.0
react-dom 15.3.0

karma 1.1.2
karma-mocha 1.1.1
karma-mocha-reporter 2.0.5
mocha 2.5.3

Node 5.8.0
npm 3.8.2
Mac OS 10.11.6

Repro steps:

Clone, build and test mxstbr/react-boilerplate
git clone https://github.com/mxstbr/react-boilerplate.git && cd react-boilerplate
npm run setup
npm test

All (78) tests pass.
Errors seem to appear during <FeaturePage /> tests
Testing FeaturePage only (npm run test -- --grep FeaturePage) does not produce errors.

ract-addons-test-utils is not included in the react-boilerplate project, but adding it does not remove the errors.

Can you please specify the exact version of boilerplate with which you can reproduce this? (Git commit hash would be fine.)

@gihrig Sorry, I test on my personal project. But I still have warning on react-boilerplate

@gaearon
The latest commit can be reproduce https://github.com/mxstbr/react-boilerplate/commit/71116a8f417668e068e71a68449164f32d9702e5
Travis-CI result still can see warning. https://travis-ci.org/mxstbr/react-boilerplate/builds/148634549

BTW, react-boilerplate did not use Jest. It maybe another problem.

Node v6.3.1
npm 3.10.3
Mac OS 10.11.6

@gaearon The problem has been appearing since updating react/react-dom from 15.1.0 to 15.2.0.

The react-boilerplate I tested on is
2bcd3ae
2bcd3aeb8d8e0fec7ae3bb572f168f9e252cb8ea

OK, I started looking into it in #7395.
This is not a super high priority since it’s just an errant warning and it doesn’t fail your tests.
Still, we’d like to get it fixed of course.

@gaearon I understand. Your efforts here on React (and Redux) are really appreciated!

YOU make my work awesome! 🎉

@gaearon FWIW I am seeing a lot of these warnings in tests that feature uncontrolled input elements. I'm using enzyme's mount() API. Using 15.3.0.

edit: ended up being in those tests by coincidence it seems

@nathanmarks If you could find a minimal repro this would be helpful. The one in react-boilerplate is very flaky and the warning disappears when I try to trim it down.

I'll give it a shot tonight 👍

@gaearon I've got a fairly minimal repo (more than react-boilerplate at least) which produces the error in testing after doing TDD for a while; it's not _always_ present though. As best I can tell, it seems to happen the longer I keep watching/running. I'll try to create a few simple tests/components to try to trigger it tonight - I'll report back if I discover how to trigger it reliably. _Pardon if I'm just adding to the noise for now though._

@tsnieman any luck? I'm having one heck of a time trying to create a minimal repro case. I've noticed that the missing element is from a previous mount and is the deepest node from that mount.

I'm getting some really extreme cases too.

@tsnieman by any chance are you using jsdom? I noticed that when I run the same tests on karma+phantomjs that I get significantly fewer warnings.

@nathanmarks Alright, so I did a bunch of TDD to try to trigger this again and discovered some odd stuff.

  • I cannot get this to occur on my desktop using this repo
  • I can get this to occur on my laptop using the exact same repo

Here's steps for triggering the repo on my laptop:

  • have a clean repo installed (EDIT: as you'll see below, this was less "clean" in my initial testing than it should have been)
  • npm run test to start jest
  • add an extra line of whitespace to a file (for example, src/components/StarButton.js) to trigger the test
  • :exclamation: the debugID error occurs (numbered from debugID 3 all the way through debugID 59)

Doing the exact same steps doesn't reproduce the error on my desktop.

Thinking about what might cause this given that situation, I decide that it is most likely a package difference between the two since this should ONLY occur in react < 15.3.0. So I do an npm list on my laptop and, lo and behold, it emits an error/warning that I'm only on react/react-dom 15.2.1 (against my package.json specification). I went ahead and just deleted node_modules/react/ and node_modules/react-dom, ran npm i and then tried my test case above again. Success! No more error! :tada:

It seems that, in my case, it was that my dependency on _one_ of my machines was out of date.

tl;dr: deleted node_modules and reinstalled, now everything works

I hope this fix works for you too.

I just did a new clone (git hash b496aa5215806f825eed7edbf091970dec17a7f2), into a new directory.

When I npm install and npm test I get 40 errors, all referencing debugID 17. The errors all appear between the first and second test of <FeaturePage />.

Removing all blank lines from the FeaturePage/tests/index.test.js file does _not_ remove the errors.

@tsnieman Wish that were the case on my end! Glad you got it sorted out 👍

For what it may be worth, I just cloned @tsnieman's repo (git hash 5af07331b4d7e0513794ef6c6b2e585378a896fe) then npm install and npm start the app seems to work as expected.

I must remove --watch from the test script to get any test results to show on screen. Then 70 tests run and pass. There are numerous errors (but no test failures) and no Missing element for React debugID errors.

If it is any help to anybody, here is probably more minimal boilerplate with the same problem with npm test https://github.com/aocenas/react-starter-kit (e5e0d7fd65f819782873ea0a6b2b7b61271e73b5).

@aocenas Just cloned (e5e0d7fd65f819782873ea0a6b2b7b61271e73b5), installed and tested, no errors.

Have you recently done a fresh install or deleted node_modules?

npm test

> [email protected] test /Users/glen/Documents/JavaScript/Research/react-starter-kit
> jest --config jest.json

Using Jest CLI v14.1.0, jasmine2, babel-jest
 PASS  __tests__/Clicker.test.js (1.179s)
1 test passed (1 total in 1 test suite, run time 2.451s)

@gihrig This is me after clean install:

git clone https://github.com/aocenas/react-starter-kit.git
cd react-starter-kit/
npm install
npm test

[09:00:16][react-starter-kit]$> npm test

> [email protected] test /Users/andrejocenas/dev/react-starter-kit
> jest --config jest.json

Using Jest CLI v14.1.0, jasmine2, babel-jest
Running 1 test suite...Warning: ReactComponentTreeDevtool: Missing React element for debugID 2 when building stack
Warning: ReactComponentTreeDevtool: Missing React element for debugID 2 when building stack
Warning: ReactComponentTreeDevtool: Missing React element for debugID 2 when building stack
Warning: ReactComponentTreeDevtool: Missing React element for debugID 2 when building stack
 PASS  __tests__/Clicker.test.js (1.099s)
1 test passed (1 total in 1 test suite, run time 3.389s)

My node --version is v6.3.1, maybe thats the difference?

@aocenas Just updated to node 6.3.1

OS X 10.11.6
node -v 6.3.1
npm -v 3.10.5
git clone https://github.com/aocenas/react-starter-kit.git
cd react-starter-kit/
npm install
npm test

react-starter-kit glen$ npm test

> [email protected] test /Users/glen/Documents/JavaScript/Research/react-starter-kit
> jest --config jest.json

Using Jest CLI v14.1.0, jasmine2, babel-jest
 PASS  __tests__/Clicker.test.js (0.805s)
1 test passed (1 total in 1 test suite, run time 2.256s)

PS. still get errors as described above after updating to node 6.3.1 and rebuilding node_modules.

Can you try sticking "persistModuleRegistryBetweenSpecs": true into your config and whether that makes these warnings go away? We are gonna ship with this as a default in the next major of Jest and it is annoying that we haven't done this before.

Jest actually resets all the modules in between calls to it to give even more isolation. So doing something like:

it('works', () => {
  const sum = require('sum');
  sum(1, 2);
});

it('works too', () => {
  const sum = require('sum');
  sum(1, 2);
});

both "sum" modules will actually be different instantiations of the module. So if you don't want to change the option above, you can also inline all your requires manually:

it('works', () => {
const React = require('React');
expect(

).;
});

When we persist the module registry, both of them will be the same (=== is true). The downside is that you might have module local state between tests that is carried over. I think since people decided to predominantly use import statements in new code, this option makes no sense by default any more.

When we persist the module registry, both of them will be the same (=== is true). The downside is that you might have module local state between tests that is carried over. I think since people decided to predominantly use import statements in new code, this option makes no sense by default any more.

@cpojer You may be onto something here. I'm running Mocha so I can't implement your suggestion, but it got me thinking...

The crop of errors I get occur in the <FeaturePage /> tests. So, I commented out the test function bodies and related imports. Now the FeaturePage tests run and "pass" without errors, but similar errors occur on the <HomePage /> tests, which run just after the FeaturePage tests.

Previous to commenting the FeaturePage tests, the HomePage tests ran without errors. This suggests that the errors are not related to the test, per se, but are (possibly) caused by a resource limitation or conflict of some kind.

@cpojer in my case the "persistModuleRegistryBetweenSpecs": true helped, no more warnings after changing that setting. But I have only one it() call in my spec so I would assume that the "reseting of registry in between calls to it" does not happen.

Also if I inline my requires into the it() call as in your example, the warning disappears.

@aocenas @gihrig Have you guys seen warning volume like this? Check this build log (worst case is at line 937 in the log): https://travis-ci.org/callemall/material-ui/builds/151227063

Also note that the mocha test suite runs twice, once using node (jsdom for the DOM) and once using karma. There are a TON more debug errors in the jsdom run.

@aocenas that is because Jest resets the registry before every test. So if you have required React already, it might get re-required (or inline-requires will be re-evaluated).

@nathanmarks All of the errors I'm seeing occur in one block, whether run local or on Travis, and my test suit only runs once. But then I have only 83 tests.

This is also occurring without Jest in TechnologyAdvice/Stardust, 100s or 1000s of these errors:

ERROR: 'Warning: ReactComponentTreeDevtool: Missing React element for debugID XXX when building stack'

I checked to ensure React and ReactComponentTreeDevtool are not being called more than once using a console.log as @gaearon used above. Each is called only once at the start of tests.

I've also tried executing a single test file in my test bundle and _some_ errors persists. I have not figured out what exactly causes the error, but it is related to certain tests running in succession as isolating some tests seems to resolve some of the issues.

node                                  v6.2.1
npm                                   v3.9.3

react                                 ^15.3.0
react-dom                             ^15.3.0
react-addons-test-utils               ^15.3.0

karma                                 ^0.13.22
karma-cli                             ^1.0.0
karma-coverage                        ^1.0.0
karma-mocha                           ^1.0.1
karma-mocha-reporter                  ^2.0.0
karma-phantomjs-launcher              ^1.0.0
karma-phantomjs-shim                  ^1.4.0
karma-webpack-with-fast-source-maps   ^1.9.2

chai                                  ^3.3.0
chai-enzyme                           ^0.4.1
dirty-chai                            ^1.2.2
enzyme                                ^2.2.0
mocha                                 ^2.3.3
phantomjs-prebuilt                    ^2.1.7
sinon                                 ^1.17.3
sinon-chai                            ^2.8.0

@levithomason Sounds very similar to what I'm experiencing.

Aye, I may delve into this further at some point. Right now it is just annoying but not actually breaking anything.

@levithomason Ditto. Next time I look into it I'm going to try track down my root cause rather than trying to create a simple repro, none of the simple repros seem to work.

The OP error has disappeared for me using the latest build.

@yaycmyk would you mind posting which versions of which modules you are on?

I think one of my 15.3.1 PRs fixed this, although I don’t know which one.
I can no longer reproduce this with react-boilerplate.
I used [email protected], [email protected], and [email protected].

Confirmed 15.3.1 works on TechnologyAdvice/Stardust. Thanks much!

I can no longer reproduce this with react-boilerplate

I have confirmed this to true, problem resolved! Thank you @gaearon 🎉

Thank you very much @gaearon, can confirm 15.3.1 resolves the issue.

I spent some time trying to make sense of the issue in the react-boilerplate project. What I found doesn't add much value but I thought it might be worthwhile sharing my findings, it certainly is a curly one.

In the <Img /> tests, the component is shallow rendered twice.

  • If you render it once or three times the issues would disappear.
  • If you add an additional expect test to the existing test case, the issues would disappear.

I tried many many other scenarios but they did not help.

No warnings

describe('<Img />', () => {
  // it('should render an <img> tag', () => {
  //   const renderedComponent = shallow(<Img src="test.png" alt="test" />);
  //   expect(renderedComponent).to.have.tagName('img');
  // });

  it('should have an alt attribute', () => {
    const renderedComponent = shallow(<Img src="test.png" alt="test" />);
    expect(renderedComponent).to.have.attr('alt', 'test');
  });
});

No warnings

describe('<Img />', () => {
  it('should render an <img> tag', () => {
    const renderedComponent = shallow(<Img src="test.png" alt="test" />);
    expect(renderedComponent).to.have.tagName('img');
  });

  it('should have an src attribute', () => {
    const renderedComponent = shallow(<Img src="test.png" alt="test" />);
    expect(renderedComponent).to.have.attr('src', 'test.png');
  });

  it('should have an alt attribute', () => {
    const renderedComponent = shallow(<Img src="test.png" alt="test" />);
    expect(renderedComponent).to.have.attr('alt', 'test');
  });
});

No warnings

describe('<Img />', () => {
  it('should render an <img> tag', () => {
    const renderedComponent = shallow(<Img src="test.png" alt="test" />);
    expect(renderedComponent).to.have.tagName('img');
  });

  it('should have an alt attribute', () => {
    const renderedComponent = shallow(<Img src="test.png" alt="test" />);
    expect(renderedComponent).to.have.attr('alt', 'test');
    expect(renderedComponent).to.have.attr('alt', 'test');
  });
});
Was this page helpful?
0 / 5 - 0 ratings