Fixing Async Calls Missing Callbacks

I recently updated to the latest stable version of node (v7.5.0) with the following command:

$ nvm install stable --reinstall-packages-from=node

and when I ran my ios-triage cli app, I saw several DeprecationWarning messages:

(node:3958) DeprecationWarning: Calling an asynchronous function without callback is deprecated.

Initially I was pretty excited because I recently taught myself node and as a noob I knew I was missing some callbacks which was preventing my async.parallel final function to not run. But the warning wasn’t sufficiently verbose as I needed to know where I was missing the callback.

Tracking down the issue

After a quick google, I discovered you can actually call node with the --trace-deprecation flag which will supply the stacktrace enabling easier debugging. While this is well documented, I didn’t even know what to search for however Google quickly landed me on this stackoverflow question. Below you can see how that helped me quickly pinpoint the cause of error:

$ node --trace-deprecation index.js 
9:40:20 AM - info: processed app data
9:40:20 AM - info: backup files processed and written to disk
(node:3983) DeprecationWarning: Calling an asynchronous function without callback is deprecated.
at maybeCallback (fs.js:96:42)
at Object.fs.writeFile (fs.js:1192:14)
at /Users/hiro/git/ios-triage/index.js:623:8
at /Users/hiro/git/ios-triage/node_modules/async/dist/async.js:3694:9
at /Users/hiro/git/ios-triage/node_modules/async/dist/async.js:356:16
at replenish (/Users/hiro/git/ios-triage/node_modules/async/dist/async.js:877:25)
at iterateeCallback (/Users/hiro/git/ios-triage/node_modules/async/dist/async.js:867:17)
at /Users/hiro/git/ios-triage/node_modules/async/dist/async.js:840:16
at /Users/hiro/git/ios-triage/node_modules/async/dist/async.js:3691:13
at apply (/Users/hiro/git/ios-triage/node_modules/async/dist/async.js:21:25)

Error code and fix

m there, things were pretty simple. In the first few days of getting my mind wrapped around async programming (my first language besides Basic was Pascal and then primarily python), I had even noted in my code that I might need to handle the callback since I wasn’t calling fs.writeFileSync.

This is my faulty code:

// FIXME should catch errors, maybe use callbacks?
fs.writeFile(path.join(processedPath,'pprofiles.json'), pprofilesJSON, 'utf8');
callback(null,"processed pprofiles");

and here’s the simple fix which captures and handles the callback from writeFile (note: since I’m using the excellent async library I choose not to callback with the error but simply note and handle it in my code):

// fixed
fs.writeFile(path.join(processedPath,'pprofiles.json'), pprofilesJSON, 'utf8', function (err) {
  if (err) {
    logger.debug("error writing pprofile data to disk with error: %s", err);
    callback(null, "error writing pprofile data to disk");
  } else {
    callback(null, "wrote pprofile data to disk");
  }
});
About Andrew Hoog
I like to tinker in mobile forensics, security, tools development and nodejs. I’m an author, inventor, expert witness and co-founder of NowSecure.