ProblemDetail class

The body of an error response in the standard JSON form of RFC 9457 (application/problem+json): a status, a title, a detail message and any extra fields.

It gives every error of an API the same shape, so clients can read them all with the same code. The web server already answers its own errors this way (a missing parameter, an invalid body, an unknown path). Return one from a controller or an @ExceptionHandler method to answer an application error the same way: the server writes it with its status, as application/problem+json, and fills instance with the request path when it is not set. On the client side, ProblemDetail.fromJson reads such a body from an error answer.

// In a @ControllerAdvice: an unknown book is a 404 problem that also
// names the ISBN.
@ExceptionHandler()
ProblemDetail notFound(BookNotFoundException e) =>
    ProblemDetail.forStatusAndDetail(HttpStatus.notFound, 'No book')
      ..setProperty('isbn', e.isbn);
// {"type": "about:blank", "title": "Not Found", "status": 404,
//  "detail": "No book", "instance": "/books/978-0", "isbn": "978-0"}

Spring (Java):

@ExceptionHandler
ProblemDetail notFound(BookNotFoundException e) {
  ProblemDetail problem =
      ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, "No book");
  problem.setProperty("isbn", e.getIsbn());
  return problem;
}

Constructors

ProblemDetail(int status, {Uri? type, String? title, String? detail, Uri? instance, Map<String, Object?>? properties})
A problem with status and any of the standard members; type defaults to blankType.
ProblemDetail.forStatus(int status)
A problem with status only; its title will be the status's reason phrase (Not Found for 404).
factory
ProblemDetail.forStatusAndDetail(int status, String? detail)
A problem with status and a detail message for the client; the most common way to make one.
factory
ProblemDetail.fromJson(Map<String, Object?> json)
Reads a problem from its decoded JSON, such as the body of an error answer received by a client. Members other than the standard five go to properties. A missing status is read as 500.
factory

Properties

detail ↔ String?
An explanation of this particular error for the client, such as No book 978-0.
getter/setter pair
effectiveTitle → String?
The title, or the status's reason phrase when it is null; null only for a status without a known phrase.
no setter
hashCode → int
The hash code for this object.
no setterinherited
instance ↔ Uri?
A URI for this particular error, usually the request path; a server sets it to the path when it is null.
getter/setter pair
properties → Map<String, Object?>
Extra members, written into the JSON next to the standard ones; for example the field errors of a failed validation, under errors.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
status ↔ int
The HTTP status code. When a server writes the problem, the response gets this status.
getter/setter pair
title ↔ String?
A short, human-readable summary of the kind of problem; when null, the JSON uses the status's reason phrase (see effectiveTitle).
getter/setter pair
type ↔ Uri
A URI naming the kind of problem, for clients that tell problems apart by type (https://example.com/problems/out-of-stock); blankType when there is none.
getter/setter pair

Methods

noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
setProperty(String name, Object? value) → void
Adds the extra member name with value to properties, replacing an earlier value.
toJson() → Map<String, Object?>
The JSON object: type, effectiveTitle, status, detail and instance (leaving out nulls), then properties. A property with a standard name replaces that member.
toString() → String
A string representation of this object.
override

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Properties

blankType → Uri
about:blank, the default type: the problem has no type of its own, and the status says what kind of error it is.
final