Making API Errors More Transparent
Time to read: 2 minutes
When learning how to use a new tool or service, the learning process usually goes something like this:
-
Read the README, or some documentation.
-
Write some code and try to run it.
-
Run into an error.
-
Determine what went wrong; go back to step 1.
There are a few keys to going through this process efficiently. One is to have a tight feedback loop between writing code and learning what went wrong; this is why developers put so much stake in ensuring that tests don't hit the disk or go over the network, things that slow down tests and hurt this loop.
Another key is ensuring that when you make a mistake, it's simple to determine what went wrong. What we were finding during our user testing was that it was difficult for new users to determine what went wrong when they used our client libraries. Consider a case where a user doesn't provide the correct Auth Token.
from twilio.rest import TwilioRestClient
token = ""
client = TwilioRestClient("AC123", token)
client.messages.create(...) # Etc, etc
When this request went to the API, it generated this fairly confusing stack trace:
Traceback (most recent call last):
File "tmp/errors.py", line 7, in <module>
url="http://twimlets.com/holdmusic?Bucket=com.twilio.music.ambient")
File "/Users/kevin/code/twilio-python/twilio/rest/resources/calls.py", line 115, in create
return self.create_instance(kwargs)
File "/Users/kevin/code/twilio-python/twilio/rest/resources/base.py", line 263, in create_instance
data=transform_params(body))
File "/Users/kevin/code/twilio-python/twilio/rest/resources/base.py", line 145, in request
resp = make_twilio_request(method, uri, auth=self.auth, **kwargs)
File "/Users/kevin/code/twilio-python/twilio/rest/resources/base.py", line 101, in make_twilio_request
raise TwilioRestException(resp.status_code, resp.url, message, code)
twilio.TwilioRestException: HTTP ERROR 401: Authenticate
https://api.twilio.com/example
In testing we noticed the actual error - "HTTP ERROR 401: Authenticate" is hard for new users to parse, against the noise of the stack trace.
Part of the confusion - the one word error message - has an easy fix. Making it easier for people to parse a stack trace is a little trickier.
More Verbose Errors
We decided to try and print more information when a request comes up in an error. Specifically, we print out the method and URI you sent to Twilio, the error message, and a link to more information, all on separate lines. To make the error more visible, we use ANSI escape sequences to print out the errors in different colors.
We use several helper functions to print out the escape sequences:
def red(words):
return "\033[31m\033[49m%s\033[0m" % words
It's important to note that different users have different default terminal background colors, so you'll need to set a consistent, bland background color as well.
One obvious worry is that we can't know how people are going to use the exception object that they receive from us. They might put it directly into a web UI, in which case the ANSI escape codes would appear as silly as they do above. To protect against this, we check if the standard error output is linked to a terminal, and only display the colorful error message if it would get printed to a terminal.
import sys
if hasattr(sys.stderr, 'isatty') and sys.stderr.isatty():
return colorful_error_message()
else:
return "HTTP ERROR {status}: {message}".format(status=self.status,
message=self.message)
We hope this new format is helpful to new users and experts alike. We are trialing it on the latest version of twilio-python, and welcome your feedback about its utility in helping you build your Twilio app.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.