Error handling
Problem Details
Problem Details for HTTP APIs (RFC 9457, obsoletes RFC7807) defines a simple JSON format to convey additional information about an error to an API consumer. This information complements the HTTP status codes [RFC7231].
For any problem occurred during processing, whether it be caused by the client or the server, the API provider supplies
-
a suitable status code: 4xx for consumer or 5xx for server errors
-
a RFC 9457 problem detail message
Rule: Use of RFC 9457 Problem Details [err-problem]
Any information on a problem SHOULD be provided in the Problem Detail format, as specified in Problem Details for HTTP APIs (RFC 9457, which obsoletes RFC 7807) :
-
the media type for problems SHOULD be
application/problem+json -
status: the HTTP status code -
type: a unique identifier for the type of the problem that MUST remain stable over time. It can be used by API clients during problem handling. -
title: a short summary of the problem type in English -
instance: a unique identifier of the problem instance. It could be used to track the message for support purposes. -
detail: consumer-friendly information about the specific failing request. It MAY be localized using language negotiation. -
additional properties may be added to provide more structured information on the problem
Consumers SHOULD NOT parse the title or detail properties to extract information; additional properties are a more suitable and less error-prone way to obtain such information.
The Problem Details response body MAY be absent when the HTTP status code itself provides sufficient information (e.g. for 405 Method Not Allowed, 406 Not Acceptable or 415 Unsupported Media Type).
This guide applies following additional restrictions on the Problem Details structure:
-
typeandinstanceSHOULD be specified as absolute URIs in order to avoid issues when resolving relative URIs (see Links) -
The
typeproperty, a stable identifier for the type of problem, is REQUIRED instead of optional -
a new optional
hrefproperty SHOULD be used to provide a URI to human-readable documentation on the problem type instead of dereferencing thetypevalue
Note that using href instead of type for documentation intentionally deviates from the recommendation in the RFC.
href allows use of a URL for documentation purposes that may change over time, while type can be specified as a URN that must remain stable.
This is especially useful for API-specific problem types for which the documentation URL may depend on technical aspects, like deployment environment.
POST /enterprises/abcd731645/employees
{
"ssin": "98765432109",
"givenName": "John",
"familyName": "Doe"
}
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
BelGov-Trace-Id: d9e35127-e9b1-4201-a211-2b52e52508df
{
"type": "urn:problem-type:belgif:badRequest",
"href": "https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html",
"title": "Bad Request",
"status": 400,
"detail": "The input message is incorrect",
"instance": "urn:uuid:123456-1234-1235-4567489798",
"issues": [
{
"type": "urn:problem-type:belgif:input-validation:schemaViolation",
"href": "https://www.belgif.be/specification/rest/api-guide/issues/schemaViolation.html",
"title": "Input isn't valid with respect to schema",
"detail": "enterpriseNumber abcd731645 should be numeric",
"in": "path",
"name": "enterpriseNumber",
"value": "abcd731645"
},
{
"type": "urn:problem-type:belgif:input-validation:referencedResourceNotFound",
"href": "https://www.belgif.be/specification/rest/api-guide/issues/referencedResourceNotFound.html",
"title": "Referenced resource not found",
"detail": "No person with ssin '98765432109' exists",
"in": "body",
"name": "/ssin",
"value": "98765432109"
}
]
}
Problem:
description: |
A Problem Details object (RFC 9457).
Additional properties specific to the problem type may be present.
type: object
properties:
type:
type: string
format: uri
description: An absolute URI that identifies the problem type
default: about:blank # kept for backwards-compatibility, type will be mandatory in problem-v2
href:
type: string
format: uri
description: An absolute URI that, when dereferenced, provides human-readable documentation for the problem type (e.g. using HTML).
title:
type: string
description: A short summary of the problem type. Written in English and readable for engineers (usually not suited for non technical stakeholders and not localized).
example: Service Unavailable
status:
type: integer
format: int32
description: The HTTP status code generated by the origin server for this occurrence of the problem.
minimum: 400
maximum: 600
exclusiveMaximum: true
example: 503
detail:
type: string
description: A human-readable explanation specific to this occurrence of the problem
instance:
type: string
format: uri
description: An absolute URI that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.
Rule: Problem type [prb-type]
Problem type SHOULD be specified as a URN in one of following formats:
-
urn:problem-type:<org>:<api>:<type> -
urn:problem-type:<org>:<type>
with:
-
<org>: a short identifier for the organization -
<api>: name of the API. It MAY be used for API-specific problem types -
<type>: type of the problem in lowerCamelCase
A description of an API-specific problem type MAY be provided as a reference data resource : /refData/problemTypes/{problemType}.
If provided, at least the HTML media type SHOULD be supported.
Reverse FQDN notation for <org> is not recommended in order to keep the identifiers short and readable.
{
"type": "urn:problem-type:exampleOrg:socialStatus:searchCriteriaTooWide",
"href": "https://api.example.org/demo/v1.be/socialStatus/v2/refData/problemTypes/urn:problem-type:exampleOrg:socialStatus:searchCriteriaTooWide",
"status": 400,
"title": "Search criteria should be more specific",
"detail": "Only one search parameter specified. Please specify at least two.",
"instance": "urn:uuid:123e4567-e89b-12d3-a456-426614174000"
}
Rule: Error sanitization [err-sanit]
A problem MUST NOT leak sensitive implementation and infrastructure details. Providers must strip this information (e.g. DB error codes, internal hostnames, stacktraces) before returning the problem detail to the consumer.
E.g. this should not be returned to a client:
HTTP/1.1 500 Internal Server Error
Server: Apache-Coyote/1.1
Content-Type: application/problem+json
{
"type": "urn:problem-type:belgif:internalServerError",
"instance": "urn:uuid:ac19acc6-5e11-4b2a-8c10-f9680998d07a",
"title": "Internal Server Error",
"detail": "Unexpected error code 24879 in server product XYZ v1.0.1",
"stackTrace": [ [
"EJBException: java.lang.RuntimeException: Something horrible happened on the server",
"org.jboss.as.ejb3.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:191)",
"org.jboss.as.ejb3.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:282)",
"org.jboss.as.ejb3.CMTTxInterceptor.required(CMTTxInterceptor.java:345)",
"org.jboss.as.ejb3.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:243)"
],
[
"Caused by: java.lang.RuntimeException: Something horrible has happened on the server",
"sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
"sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)",
"sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)",
"java.lang.reflect.Method.invoke(Method.java:606)"
]
]
}
Rule: Default problem response in OpenAPI [prb-defaul]
Problem types that may occur on all or most operations of an API (e.g. a missing permission, an internal server error, request violates schema, …) SHOULD NOT each be documented explicitly in its OpenAPI description, as this would clutter the spec and make it difficult to keep up to date.
Rather, a default Problem response SHOULD be added to each operation. Operation-specific problem types should still be documented.
Specifying a default problem response ensures compatibility with clients that perform strict OpenAPI validation on response messages.
ProblemResponse from problem-v1.yaml)/orders/{orderId}/archive:
post:
summary: archive the order
operationId: archiveOrder
parameters:
- "$ref": "#/components/schemas/OrderId"
responses:
"200":
"$ref": "#/components/responses/OrderArchivedResponse"
"409":
description: Order can not be archived when it's not completed
content:
application/json:
schema:
"$ref": "#/components/schemas/InvalidStateProblem"
default:
"$ref": "./problem/v1/problem-v1.yaml#/components/responses/ProblemResponse"
Standardized problem types
A list of problem types is standardized in this guide for reuse across all REST APIs.
They are defined as URNs of format urn:problem-type:belgif:<type>.
href links to descriptions of standardized problem types will change in the future to recommended format containing full problem type identifier without HTML extension. Current URLs will redirect.
|
The library belgif-rest-problem-java provides implementation support for these problem types when developing Java applications.
The standardized problem types are described in their individual pages in the annex:
| Status code | Problem type |
|---|---|
400 |
|
401 |
|
401 |
|
401 |
|
403 |
|
403 |
|
404 |
|
413 |
|
429 |
|
429 |
|
500 |
|
502 |
|
503 |
problem-v1.yaml provides a reusable InputValidationProblem schema that extends the Problem schema with a list of issues for use in badRequest and resourceNotFound problems. Following standard issue types are defined for badRequest:
| Issue type |
|---|
|