Debugging Twilio - HTTP 405 Not Allowed

There is nothing more discouraging than hearing “We’re sorry. An application error has occurred.” over and over again while debugging a Twilio application. I experienced this recently while rehearsing the five-minute Twilio demo I’ve given dozens of times before. This post will examine a specific error you may run into when making phone calls with Twilio.

The Issue

I used Twilio’s NodeJS helper library to make a call to a specific phone number. The code looked like this (I’ve redacted the actual phone numbers used):

twilioClient.makeCall({
    to: ‘+1XXXXXXXXXX’, // Destination number
    from: ‘+1XXXXXXXXXX’, // My Twilio number
    url: 'http://brodan.biz/call.xml' // TwiML instructions
});

Syntactically, there is nothing wrong with this function. I ran the script and received the phone call, but was greeted by the haunting “We’re Sorry, an application error has occurred.” message when I picked up.

I couldn’t think of what could possibly be wrong. I had written this code over and over again and hadn’t change anything. I opened up my Twilio logs (the best place to look when debugging Twilio apps) and examined the most recent phone call I sent. 'Under Error and Warning Notifications', here is what I saw:

Error: 11200 HTTP retrieval failure

Description: An attempt to retrieve content from http://brodan.biz/call.xml returned the HTTP status code 405.

That’s new. Navigating to the URL in my browser displays my XML file as expected, so why can’t Twilio access it? The request I made to retrieve my application’s TwiML returned a 405 Not Allowed status. I looked further into the status code and found the following (source):

A request was made of a resource using a request method not supported by that resource; for example, using GET on a form which requires data to be presented via POST, or using PUT on a read-only resource.

The Explanation

I scrolled further down in my Twilio logs and observed at the 'Request Inspector'. It displayed the following return body:

<html>
    <head>
        <title>405 Not Allowed</title>
    </head>
    <body bgcolor="white">
        <center>
            <h1>405 Not Allowed</h1>
        </center>
        <hr>
        <center>nginx/1.4.6 (Ubuntu)</center>
    </body>
</html>

This helped me realized that something had changed since the last time I wrote this code.

I use a private Linode server to serve my personal website. Previously, I had been using Apache to serve static files but had since migrated to nginx. It turns out that Twilio, by default, makes a POST request when retrieving your applications TwiML. Apache’s default configuration allowed for POST requests to return static files, but nginx’s default configuration did not.

The Fix

There are two very simple approaches to fixing this problem.

You can add a single parameter to makeCall that specifies the HTTP request method to use when requesting the url parameter's value, as seen in the Twilio documentation:

twilioClient.makeCall({
	to: message.from,
	from: '+17325043641',
	url: 'http://brodan.biz/call.xml',
	method:'GET'
});

Alternatively, you can add a line to your nginx configuration file to handle 405 errors. The line you need to add is as follows:

error_page 405 =200 $uri;

An example nginx configuration would then look as such:

server {
    listen 80 default_server;

    root /var/www;
    index index.html;

    location / {
        try_files $uri $uri.html $uri/ =404;
        error_page 405 =200 $uri;
    }
}

If you found this post helpful or would like to give feedback, feel free to reach out to me on Twitter @brodan_.