REST API Exceptions in HTML instead of JSON

I have a CakePHP 3 REST API app that I’m migrating to CakePHP 5.

I’ve started with a clean CakePHP 5 install and I’m slowly moving code from the existng app. This has gone well so far. However, after setting up a RESTful route and testing error handling, I’ve found that when my resource throws an exception, e.g. when a query parameter is out of range, the response has a content type of text/html and not application/json.

In my old CakePHP 3 app, exceptions were returned in JSON format. Example:

{
    "message": "The limit parameter must be an integer between 1 and 100, inclusive.",
    "url": "/api/items/?limit=123456",
    "code": 400
}

I’ve made sure that the request’s Accept header value is application/json, and when no exception is thrown, the response is in application/json as expected. It’s only when my code throws an exception that I get an HTML response.

I’ve looked through my CakePHP 3 code to see if I set up anything special to handle exceptions, but I’m not finding anything, i.e. no custom renderes, etc. I also don’t remember customizing this; I’ve always assumed that exception handling understood to return in the same format as what’s indicated in the Accept request header value.

Is there something I’m overlooking?

Previously that was unsolicitedly handled by the request handler component (at least for JSON and XML), but that thing doesn’t exist anymore, now you have to let CakePHP know which types it is allowed to negotiate.

Open your error controller class file (src/Controller/ErrorController.php), and add the following line to the class’ initialize() method:

$this->addViewClasses([\Cake\View\JsonView::class]);

Then check out https://book.cakephp.org/5/en/controllers.html#content-type-negotiation

2 Likes

This did the trick. Thank you so much for your answer and the link to the relevant documentation.