Don't Panic

Andrew Hoog's blog on mobile security, forensics, programming and photography

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

From 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");
  }
});