Weird Errors in JS

I was met today with two error messages when continuing to build my Node.js project - one I’d seen before, the other was new. Javascript, as a dynamically-typed and interpreted language, can display strange behavior that can be tricky to understand at times.

Today I received the following error when trying to log an object:

This is me recreating the issue using a null prototype object

This is me recreating the issue using a null prototype object

This happened when I tried to concatenate a string I was printing to the console with a URL query string object:

console.log('this was the URL query string contained in the client request:' + queryString)  

To try and pin down what was happening, since I knew I could make no assumptions about the queryString object being received since I didn’t create it, I created a mock queryString object:

var queryString = {‘foo’ : ‘bar’}
console.log('this was the URL query string contained in the client request:' + queryString)

This time, I managed to print it out without any issue (even though the object didn’t actually print out and instead showed [object Object]). That output is the correct string representation of an object that hasn’t been stringified - I realized that the javascript engine was using type coercion to convert my mock object into a string (since I was concatenating it to an actual string, it was treating the whole thing as one string). I figured the engine must have been calling toString() on that object - why wasn’t this happening to the ACTUAL query object I was getting from the client request?

I opened up Chrome and used the browser console there since it lists out type methods available that can be called on a given variable. I recreated my mock query string object and, using the dropdown, saw that toString() was available to be called on it. That showed me what was happening, more or less, in my node project - by concatenating to a string, the engine was coercing my object into a string by calling toString() on it, leaving the [object Object] string representation printed to the console.

Again in Chrome, I created a null prototype object with the same key value pair that I had in my original mock queryString object. When I used the dropdown to check the prototype methods available, there was no toString() to be seen - what I guessed was happening was that the prototype of the request URL query string object was inheriting from a prototype that didn’t have the toString() method available. As a result, when trying to coerce the object type to string, the engine possibly tried calling toString(), found that it couldn’t and printed the error to the console about being unable to convert to a primitive value.

The Solution

Instead of concatenating an object of unknown origins to some user printed string, just use a comma instead of a “+” operator! This has the additional bonus of not converting (or attempting to convert) the object to a string

The Next Error

The second error I came across was when I had a block of code that I realized executed two callbacks when dealing with the same request. “Error: Can't set headers after they are sent." was what I was shown on the terminal after my server crashed - I could figure out WHAT was happening from the error message but I wasn’t sure WHY it was happening.

NodeHeaderError.png

The error message itself can be a little confusing - what’s happening in this case is that a handler callback is sending a status request and payload to our index.js file. We send a response header when the first callback is returned - we’re then calling res.end(), closing the process. A little bit further down in our handler function, we’re trying to send ANOTHER callback to the same request (even though the process has ended), resulting in our error.

The Solution

Use log statements or your preferred debugging method to figure out which function is causing the issue - once you’ve pinned it down, look for multiple callbacks responding to the same request and reduce to just one callback.