Error: Can't set headers after they are sent.

This is the error that was stymying me for hours. I was uploading an image file from an Angular.js front end to a node.js route 'user/image' and using Multer middleware the receive the uploaded file, stash it temporarily in an uploads folder, and call a method to upload it to a Microsoft Azure blob location from where I could serve the images in my app. But unfortunately I couldn't send my data back in res.send because the headers had already been sent, unbeknownst to me.

Here's my code for the part of the Multer  middleware that was the source of the issue:

onFileUploadComplete: function (file, req, res) {
  console.log(file.fieldname + ' uploaded to  ' + file.path);
  var newFileName = req.files.file[0].name;
  if (!isFileTooLarge) {
    userCtrl.uploadUserImage(newFileName, function () {
      //file param is actually an object with the path as a property
      file.path = 'http://midup.blob.core.windows.net/userpictures/' + newFileName;
      pathUrl = file.path;
      res.send(pathUrl);
      //delete file from local uploads folder
      fs.unlink('./server/uploads/' + newFileName);
    });
  } else {
    fs.unlink('./server/uploads/' + newFileName);
  }
}

In this code, I'm checking if the file is larger than the max size I've specified and if not, I want to call the uploadUserImage method. Initially I was passing a req and res into this method but not really doing anything with either of them. Here's my code for that method. You'll notice I'm console logging a res.headersSent method.

exports.uploadUserImage = function(imageName, cb) {
  //console.log('headersSent in UploadUser1 ', res.headersSent);
  var localPath = './server/uploads/' + imageName;
  blobSvc.createBlockBlobFromLocalFile('userpictures', imageName, localPath, function(error) {
      //console.log('headersSent in UploadUser2 ', res.headersSent);
    if (!error) {
      console.log('file uploaded');
      cb();
    } else {
      console.log('error on image upload is ', error);
      return error;
    }
  });
  };

Thanks to this little known res.headersSent express method that does a boolean check to see if the headers have been sent, I was able to slowly trace where my headers were being sent.

Turns out that the req and res being initially passed in as the first and second argument to uploadUserImage were being used by the call I was making to the azure blob service to upload my image there. I probably shouldn't say "being used" since in fact they had no business being passed in but after the azure blob returned it's result, the headers were indeed being sent because my console log for headersSent in UploadUser1 returned false while my console log in headersSent in UploadUser1 returned true. So, I just removed the req and res arguments and voila, it worked as expected.

So, if you are ever having trouble with the error above, start debugging using the res.headersSent method.