Structured Errors in Plumber APIs
If you’ve used the Plumber package to make R models
or other code accessible to others via an API, sooner or later you will need to
decide how to handle and report errors.
By default, Plumber will catch R-level errors (like calls to stop()) and
report them to users of your API as a JSON-encoded error message with HTTP
status code 500 – also known as Internal Server Error. This might look
something like the following from the command line:
$ curl -v localhost:8000/
> GET /status HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< Date: Sun, 24 Mar 2019 22:56:27 GMT
< Content-Type: application/json
< Date: Sun, 24 Mar 2019 10:56:27 PM GMT
< Connection: close
< Content-Length: 97
<
* Closing connection 0
{"error":["500 - Internal server error"],"message":["Error: Missing required 'id' parameter.\n"]}
There are two problems with this approach: first, it gives you almost zero
control over how errors are reported to real users, and second, it’s badly
behaved at the protocol level – HTTP status codes provide for much more
granular and semantically meaningful error reporting.
In my view, the key to overcoming these problems is treating errors as more than
simply a message and adding additional context when they are emitted. This is
sometimes called structured error handling, and although it has not been
used much historically in R, this may be changing.
As you’ll see, we can take advantage of R’s powerful condition system to
implement rich error handling and reporting for Plumber APIs with relative ease.