Hacker News new | past | comments | ask | show | jobs | submit login
Problem Details for HTTP APIs (rfc-editor.org)
176 points by stefankuehnel on March 29, 2023 | hide | past | favorite | 48 comments



FYI, a revision of this document has been approved, and should be published as an RFC soon: https://datatracker.ietf.org/doc/draft-ietf-httpapi-rfc7807b...


Awesome! Any idea of planned browser support?


Your application code running in the browser has to know how to support this. The browser doesn’t care about the shape of any JSON going or coming to/from an HTTP API.


Thanks, I don't know how I jumped to that conclusion re-reading now. Just wanted it to be the case I suppose - I think browser-integrated/'native' errors would be nice. I suppose a browser extension could do it, quite a permission to give though (I assume they can't request media type scoped permission to read responses).


ACME (RFC 8555) uses this, so I've implemented the client-side of it. It's alright. I do think it's nice to have some sort of semi-standard structure for error details. The namespace URN stuff feels like ceremony though and sometimes I wonder if the spec is a little over-engineered, but overall I'm glad there's something we can default to for public APIs.


The namespace is great - it will be useful for proxies, auth middlewares, caches and other intermediaries that can intermix with the main application.


I can't tell if I'm missing the point or this spec is.

To properly handle errors, there needs to be an exhaustive enumeration of the types of errors. This is hard to generalize across all applications and this RFC just sidesteps it entirely.

We don't need yet another way to bundle together a bunch of strings nobody ever reads and that applications will have to parse because there's no error code beyond the woefully inadequate HTTP status. If the app dev has to roll their own enumeration scheme and put this application-level error code in an extension, that's no better than just responding with the JSON they already had.


> To properly handle errors, there needs to be an exhaustive enumeration of the types of errors. This is hard to generalize across all applications and this RFC just sidesteps it entirely.

It's covered by the "type" property of the RFC-defined payload. Type is a globally (URL-based) unique value that your application can either match (and handle) or grab full details (GET url) which can be cached. This allows servers to serve new errors to old clients.

Error handling is underserved in most apps and putting it in a standard increases the probability that npm-install-library developers will do it at all.


We use this in our generic REST client[1] to emit nicer error messages to the user of the client. As much as possible our client uses best practices and open standards where applicable. If you don't use application/problem+json you just get a HTTP errors, but with application/problem+json we'll extract the human-readable error message and such.

[1]: https://github.com/badgateway/ketting


I implemented the older RFC in Java, doing a few fun things:

1. API were ultimately expected to throw a ProblemDetailsException. A response filter would catch and wrap other unexpected throwables into a problem details exception.

2. The resulting exception handler preferred [a/p+j, a/j, a/p+x, a/x, t/h] media type ordering (with abbreviated names), which meant that a browser would get HTML errors while something like curl would get application/problem+json

I considered a XSLT on the XML output, but that just seemed like going for bonus points.


JSONAPI defines a similar structured format allowing an array of errors:

https://jsonapi.org/format/#errors


I seem as slightly different beasts, with different purposes though there’s some overlap. Primarily, JSON:API may return both content and errors at the same time, it’s not an either/or proposition. This can be quite useful with collections, for example, where some things succeeded, and other things failed. These types can also be used together, for example I’ve used problem details for catch all error handlers, so if one resource starts throwing unhandled errors we still get structured data instead of some random 500 status page that tells me nothing, while using JSON:API to let the resources communicate errors that are perhaps less unexpected (e.g. validation errors.)

It’d be nice though if JSON:API just referred to problem details and added extensions for the JSON:API specific bits.


I don't think this is true, as section 7.1 states:

> The members data and errors MUST NOT coexist in the same document.


Indeed you are right, I stand corrected. Thank you!


I actually don't like the idea of mixing standard fields (such as title, type, detail and instance) on the SAME level as the extensions.

I would have moved them to a single property that is freeform. Makes parsing easier IMO.


would be nice to add (2016) or the actual RFC number (7807) in the subject.

more from the authors btw:

https://datatracker.ietf.org/person/Mark%20Nottingham

https://datatracker.ietf.org/person/erik.wilde@dret.net


Or perhaps better to update the link to the 1 March 2023 revision: https://www.ietf.org/archive/id/draft-ietf-httpapi-rfc7807bi...

which has been approved: https://datatracker.ietf.org/doc/draft-ietf-httpapi-rfc7807b...

(I didn't realise, credit to https://news.ycombinator.com/item?id=35366691)


On practical thing I took away from this:

If you omit the "type", the message has no additional semantics beyond that of the HTTP status code. So this provides a standard for error responses with JSON bodies:

    {
        "title": "Not Found",
        "status": 404,
        "detail": "The file you are looking for doesn't exist."
    }


The idea seems okay, a standard method to report errors would be quite nice to have. But why JSON and XML only? Why no header-based option?


Aside from technical limitations of HTTP headers, why do you need a header-based solution?


So that I don't have to stuff a JSON or an XML parser on the client.

Section 3.1 https://www.rfc-editor.org/rfc/rfc7807#section-3.1 suggests there's nothing in there that couldn't be done with response headers. A couple of URIs, some strings, and a useless status field. Useless because in reality a client will always have to obey the response status code.

Extensions can be easily done via headers. x-amz-... have paved the path.


A header-only solution would still need a parser, because it formally includes arbitrary nested structures. There’s certainly prior art for that in headers, and you may even have a capable parser already at hand. But for better or worse that’s probably a much less likely scenario than having a JSON or XML parser.

Even so, the RFC specifically addresses arbitrary formats, and there’s nothing in it which would preclude headers as one such format.


> because it formally includes arbitrary nested structures

In case of XML, yes, in case of JSON... where? Extensions?

> Even so, the RFC specifically addresses arbitrary formats, and there’s nothing in it which would preclude headers as one such format.

Yeah, the Appendix B is mightily confusing. It basically says "in case of specific requirements, do as you please":

   This specification does not make specific recommendations regarding
   embedding problem details in other formats; the appropriate way to
   embed them depends both upon the format in use and application of
   that format.


> In case of XML, yes, in case of JSON... where? Extensions?

Yes.

> Yeah, the Appendix B is mightily confusing. It basically says "in case of specific requirements, do as you please"

Yep! The world is your HTTP header oyster.


> Yep! The world is your HTTP header oyster.

So basically it does not address anything. I begin to wonder what’s the point of this RFC.

Was it the case “oh, we use this inside of Akamai but some of our clients require some form of a standard so can we please push this one through”?

I mean, surely if you’re going to propose a standard that suppose to address some shortcomings of HTTP, you’d do it so that it can be used by anybody without any dependency other than HTTP itself. No?


> So basically it does not address anything. I begin to wonder what’s the point of this RFC.

If it doesn’t solve a problem you have, it’s okay to recognize that without categorically declaring it doesn’t solve any problems. The point of the RFC is very clearly stated, and its scope is intentionally limited and flexible.

The problem it identifies is a common set of error conditions, and some general ways that those general conditions might carry more detail. The solution proposed is a general way of modeling those, with some proscribed semantics for popular data formats and a less proscribed and very permissive way to incorporate the same approach in any format whatsoever.

> I mean, surely if you’re going to propose a standard that suppose to address some shortcomings of HTTP, you’d do it so that it can be used by anybody without any dependency other than HTTP itself. No?

They did do that. If you’re so insistent that it use headers only and no semantics specified outside of HTTP, you must already know that the Link header has all of the structural semantics you’d need to implement the same data structures. You’d still need to parse the header, but again if you’re so invested in that particular approach you probably already have a solution to that.

If your expectation is that this RFC uses only HTTP headers but comes with built in semantics for arbitrary structured data within HTTP headers, your demand is impossible to satisfy. HTTP headers are inherently a dictionary relation of strings to strings, until HTTP itself is modified to accommodate something more sophisticated. And if anyone tried to make that change it would face far more backlash than “feel free to pack whatever data into that dictionary you want, if that’s your thang”.


HTTP already provides status code and reason phrases. Response header may not be the best place to provide details, size is limited, it doesn't really allow nesting... Not saying this is impossible but it could be the reason why they didn't provide a header-based option.


At some point a standard that tries to cover every possible option becomes a bad standard.


One thing I like about this is that it strikes a good (IMO) balance between:

- address common cases with flexibility for domain specific minutiae

- explicitly call out that there are cases where it’s either redundant or insufficient

I was also struck by how `type` feels very reminiscent of XML namespace URIs, but it’s great that there’s a SHOULD recommendation that the URIs resolve to something meaningful in resolving problems.

Overall it’s not an earth shattering idea, but it seems like a pretty good baseline approach to solving something that’s often either neglected or reinvented.


I don't... entirely mind this, this is how most APIs respond errors anyway in my experience, especially if they expect them to both be used for fully fledged browser clients that display errors and for API-only clients.

The only thing I don't like here is the "type" parameter and how its expected to be an URI. That will only hamper implementation, considering most API documentation isn't distributed as individual error pages. Most of the time you either have a PDF document (for private APIs), a single big HTML page (which to be fair, can be anchored) or in some cases, physical documentation.

Personally I'd just have allowed type to be a simple string that informs the machine about the type of exception that occurred, and expect people implementing the API to figure out what that means (ie. Through external documentation) instead of making it a URI.

The out of credit example would have a "type" of "OutOfCreditException" in my suggestion, of course adjustable by whatever is preferred.

This RFC is just a slightly pointless standardization that has one weird thing in it that nobody actually does, which to be fair "here's what were all doing but slightly different, so get to work" can describe a lot of RFCs.


Well, the spec says that the type is a URI, only encouraging implementers to use URIs that can be dereferenced to human readable documentation but not forcing it.

You’re free to use whatever URI suits your purpose, like a URN or maybe even your on scheme. All the spec asks is that it’s a URI which is a wide and flexible range of identifiers, only a subset of which actually point somewhere.


I fully expect people to adopt something like "error:validation-error" for the type field, followed by decades of arguments whether that's ok (it follows the URI format, but does it identify a resource?)


I mean, isn't that how it should be though? Pick a scheme (preferrably not in the IANA registry), design something, figure out what works in practice, optionally find it so nice that you'd like to share it with the world and make an RFC to register a new scheme. Rinse and repeat.


Not in this case, no; not when it's trivial to put a URL there.


The sort of people that deliberately use the Problem Details format rather than rolling their own are the sort of people who will agonise over the URIs they choose, making sure they’re meaningful in some way.

(I’m simplifying, of course, but I think it’ll be a decent generalisation.)


I agree with you. But it's nice to have some reference about how we can return a response error. I already see too much creativity, weird formats and useless informations in many APIs, so this can work as a basic quality threshold.


Its not pointless. Proxies (such as istio), caches or middlewares (like auth and validation) should be able to set errors without interfearing with the main application errors. The namespacing scheme allows that.


It's unfortunate that the spec doesn't contain custom fields to a sub-object like other RPC specs, like proto Status [1]. They should have had the message go into a field named "message" and not "detail". And have a field like "details" where the opaque type is serialized, which should be named by the "type" field. The problem is that systems with existing error types may have field name conflicts with type, title, status, detail, or instance, so we'd just dump the actual error into a custom "extension member" which by definition, isn't standard.

[1] https://github.com/googleapis/googleapis/blob/1c8a25ab153eef...


What does this mean for APIs that do response wrapping?


Not really a HTTP thing if it’s based on JSON response body, right?


What about when HTTP carries images? Or anything other than HyperText? And what is HyperText anyways? Why isn't it HTML Transport Protocol? Well, it's because HTML is not the only HyperText out there -- you can embed links in XML, XHTML, JSON, and all sorts of other things, as well as in HTTP headers.

HTTP isn't really only about HyperText, nor only about HTML -- it's about everything.


It really should've been called GRRTP, Generic Request-Response Transfer Protocol, because there is nothing in it per se that's catered to hypertext transfer specifically.

For comparison, look at FTP: it really is about the file transfer, you can tell that that is its application domain. Then look back at HTTP... yep, a generic request-response protocol, suitable for building pretty much anything else on top it.


Pretty much. But it is what it is, and it's too late to rename it now.


As sibling comment mentioned it includes an XML format definition (which itself is surprisingly restrictive, and sort of idiosyncratic for XML), I also found it odd that blesses only those two formats. But Appendix B does give guidance for use in arbitrary formats/media types.

Basically it’s format-agnostic, but it covers the two most common/likely scenarios. IMO that’s sensible enough, but it’s not ideal how much the format-agnostic aspect is deemphasized.


JSON is by far the best supported serialization format. Why does using that format make it less about HTTP?


It's for HTTP APIs, and it's XML too.


Seems like this proposal would be more appropriate as part of a JSON-specific protocol with HTTP as transport.


But what about the XML half?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: