What's going on with this Backbone/node/express 400 Bad Request error when deploying to Heroku?

I'm getting a 400 Bad Request error when deploying my Backbone.js/node.js app to Heroku.

From the logs:

Error: Bad Request
    at Object.error (/app/node_modules/express/node_modules/connect/lib/utils.js:42:13)
    at IncomingMessage.<anonymous> (/app/node_modules/express/node_modules/connect/lib/middleware/json.js:57:73)
    at IncomingMessage.emit (events.js:64:17)
    at HTTPParser.parserOnMessageComplete [as onMessageComplete] (http.js:130:23)
    at Socket.ondata (http.js:1506:22)
    at TCP.onread (net.js:374:27)

From the network tab of Chrome devtools:

enter image description here

The error does not appear when running on localhost.

enter image description here

Interestingly, a direct get to the URL works fine. A manual jQuery.ajax() call also works fine. This Backbone.sync call is the only instance that the resource fails, but it fails consistently.

What's going on with this Backbone/node/express 400 Bad Request error when deploying to Heroku? My guess would be something related to a proxy/router artifact such as x-forwarded-for but at this point I can't tell if the error is at the Backbone, express or Heroku level.

Backbone request headers (400 Bad Request)

GET /services HTTP/1.1
Host: karmr.herokuapp.com
Connection: keep-alive
Cache-Control: max-age=0
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1082.0 Safari/536.5
Content-Type: application/json
Accept: application/json, text/javascript, */*; q=0.01
Referer: http://karmr.herokuapp.com/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

HTTP/1.1 400 Bad Request
Content-Type: text/plain
X-Powered-By: Express
Content-Length: 420
Connection: keep-alive

Direct GET (200 OK):

GET /services HTTP/1.1
Host: karmr.herokuapp.com
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1082.0 Safari/536.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
X-Powered-By: Express
Content-Length: 84
Connection: keep-alive

Here are the header diffs (bigger version here):

enter image description here

I suggest you two lines of investigation:

  1. The Url is not responding JSON: Check what this URL is responding and why it is not responding a proper JSON. If you see the headers the client is expecting application/json, text/javascript, */*; q=0.01 and the URL is responding text/plain.

  2. There is a CROSS-Domain issue: Check all the issues about CROSS-Domain

I dont know if you have tried this yet, but when sending a response from your server instead of using the plain old

response.send(response to send);

try using

response.json(response to send);

instead.

I had this same error showing up and for the life of me could not find the solution, after switching it worked instantly. Hope this helps.