Skip to content
Turtle
Instagram

Trace Warnings with Node

Javascript, Node2 min read

When upgrading to Node 14, I ran into this issue where running the test suite would throw a set of warnings like so:

(node:79706) Warning: Accessing non-existent property 'cat' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
(node:79706) Warning: Accessing non-existent property 'cd' of module exports inside circular dependency
(node:79706) Warning: Accessing non-existent property 'chmod' of module exports inside circular dependency
(node:79706) Warning: Accessing non-existent property 'cp' of module exports inside circular dependency

One way of finding out what packages were throwing these warnings was by running the same command but with the --trace-warnings option:

npx cross-env NODE_OPTIONS="--trace-warnings" yarn test

This helped in pinpointing which packages needed to be updated!

Bonus

Here is a contrived example of two classes depending on each other:

// a.js
const B = require('./b');
class A {
constructor(name) {
this.name = name;
this.b = new B();
this.b.log(name);
}
}
const a = new A('cat')
module.exports = A;
// b.js
const A = require('./a');
class B {
constructor() {
this.a = A;
console.log(this.a)
}
log(stuff) {
console.log(stuff)
}
}
module.exports = B;
// package.json
"scripts": {
"build": "node a.js"
},

Now building our files gives us this warning:

$ yarn build
(node:18952) Warning: Accessing non-existent property 'Symbol(nodejs.util.inspect.custom)' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)

Now using --trace-warnings we can see where this issue is happening:

$ npx cross-env NODE_OPTIONS="--trace-warnings" yarn build
(node:18978) Warning: Accessing non-existent property 'Symbol(nodejs.util.inspect.custom)' of module exports inside circular dependency
at emitCircularRequireWarning (node:internal/modules/cjs/loader:698:11)
at Object.get (node:internal/modules/cjs/loader:712:5)
at formatValue (node:internal/util/inspect:746:30)
at inspect (node:internal/util/inspect:330:10)
at formatWithOptionsInternal (node:internal/util/inspect:1998:40)
at formatWithOptions (node:internal/util/inspect:1880:10)
at console.value (node:internal/console/constructor:327:14)
at console.log (node:internal/console/constructor:363:61)
at new B (/Users/ygaberman/programs/test/b.js:6:17)
at new A (/Users/ygaberman/programs/test/a.js:7:18)

The last two lines show us where the dependency is. This is quite useful for chasing down any circular dependencies!


Can we fix it? Yes.