I'm getting the following error. It's clearly coming from a callback passed to process.nextTick
. Given that the stack trace is virtually unusable, how do I debug this? What's going on behind the scenes, and how can I resolve this in a larger project?
TypeError: callback is not a function
at nextTickCallbackWith0Args (node.js:420:9)
at process._tickDomainCallback (node.js:390:13)
N.B. Older versions of Node had a different implementation of process.nextTick
, and spit out the following stack trace.
Uncaught TypeError: undefined is not a function
at process._tickCallback (node.js:415:13)
Node.js tick callback prefers to throw an error if the function you pass to process.nextTick
is not a function after a tick has passed, rather than telling you when you first call it.
Where a function will just get called after a tick:
// this will print "hi!", followed by "hello there"
process.nextTick(function() {
console.log('hello there');
});
console.log('hi!');
A non-function won't actually matter until the next tick:
// this will just print "hi!", and an error will be thrown later on
process.nextTick(undefined);
console.log('hi!');
Below, I'll outline two diagnostic tools you can use to track down the culprit.
longjohn
As it turns out, this kind of scenario is common enough that a tool exists to extend stack traces with information from previous ticks.
Simply install longjohn (available on npm), and require
it when your process starts. This will yield a stack trace similar to the following:
TypeError: Cannot read property 'apply' of undefined
at nextTickCallbackWith0Args (node.js:420:9)
at process._tickCallback (node.js:349:13)
at Function.Module.runMain (module.js:443:11)
at startup (node.js:139:18)
at node.js:968:3
---------------------------------------------
at Object.<anonymous> (.../example.js:3:9)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)
at node.js:968:3
Now that you have a useful stack trace, you can use your debugging skills to figure out why you're giving process.nextTick
undefined rather than a function.
Because javascript is dynamic, we can easily setup a new version of process.nextTick
(that is, we can monkey patch it) which traces the call to it, but proxies to the real nextTick function:
var nextTick = process.nextTick;
process.nextTick = function(callback) {
if (typeof callback !== 'function') {
console.trace(typeof callback + ' is not a function');
}
return nextTick.apply(process, arguments);
};
Note: I don't recommend doing this for production code, but it does make it much easier to locate where you're providing something besides a function to process.nextTick
. Remember that this is modifying the global process
variable, so it might break at some point and it's certainly not considered best practice, but it'll do nicely for finding small problems. (Addendum: and since I originally wrote this post, I've had to revise it because it broke once.)
Trace: undefined is not a function
at process.nextTick (.../example.js:5:13)
at Object.<anonymous> (.../example.js:10:9)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)
at node.js:968:3
As above, now that you have a useful stack trace, you can identify the root cause.
In terms of the internals, check out the _tickCallback
function in node.js
in the source (old link).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With