Return to site

🧩🚨 Spring Boot API error handling with ProblemDetail (RFC 9457)

· spring

🔸 TLDR

▪️ Use ProblemDetail to return consistent, machine-readable errors (status + title + detail + type + extra fields) ✅

Section image

🔸 CONTEXT

▪️ APIs often return random error shapes: sometimes {message}, sometimes {error}, sometimes HTML 😅

▪️ Clients hate guessing. Observability hates inconsistency.

▪️ ProblemDetail gives you a standard error contract (Problem Details for HTTP APIs — RFC 9457).

🔸 Snippet: custom 404 (ProblemDetail + @RestControllerAdvice)

@RestControllerAdvice
class ApiErrors {
 @ExceptionHandler(CustomerNotFoundException.class)
 ProblemDetail handle(CustomerNotFoundException ex) {
 ProblemDetail pd = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
 pd.setTitle("Customer not found");
 pd.setType(URI.create("https://lnkd.in/evfJ_kGK"));
 pd.setProperty("customerId", ex.customerId()); // 👈 custom field
 pd.setProperty("traceId", TraceId.current()); // 👈 correlation id (example)
 return pd;
 }
}

🔸 Snippet: validation errors (return a list of field issues)

@RestControllerAdvice
class ValidationErrors {
 record FieldIssue(String field, String message) {}

 @ExceptionHandler(MethodArgumentNotValidException.class)
 ProblemDetail handle(MethodArgumentNotValidException ex) {
 ProblemDetail pd = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST);
 pd.setTitle("Validation failed");
 pd.setType(URI.create("https://lnkd.in/ehDs73e5"));
 List<FieldIssue> issues = ex.getBindingResult().getFieldErrors().stream()
 .map(fe -> new FieldIssue(fe.getField(), msg(fe)))
 .toList();
 pd.setProperty("errors", issues);
 return pd;
 }
 private String msg(FieldError fe) {
 return fe.getDefaultMessage() != null ? fe.getDefaultMessage() : "Invalid value";
 }
}

🔸 Takeaways

▪️ Standardize your error shape → clients stop “parsing strings” 🧠

▪️ Set type to a stable doc URL → self-explaining API 🔗

▪️ Add safe custom fields via setProperty(...) (traceId, errorCode, errors[]) 🧾

▪️ Don’t leak internals (stacktraces / SQL / secrets) 🔒

▪️ Centralize with @RestControllerAdvice for consistency ⚙️

#SpringBoot #SpringFramework #Java #API #REST #ErrorHandling #ProblemDetail

🍃📗 Grab your Spring cert Book: https://bit.ly/springtify