RFC7807 style errors
On this page
Why Inconsistent Error Handling Breaks Production Systems
In production systems, errors are not just failures. They are contracts. If each controller returns a different error shape, if stack traces leak in some cases, if validation errors are sometimes strings and sometimes JSON, your system becomes operationally untraceable. Production symptoms: - Client teams cannot reliably parse errors. - Monitoring cannot classify failure types. - Support cannot correlate user reports with logs. - Sensitive implementation details leak in responses. Error handling must be centralized, deterministic, and safe.Incident Scenario: 500 Errors With No Traceability
After a deployment, error rates increased. Monitoring showed HTTP 500 spikes. However: - Some endpoints returned plain text. - Others returned HTML error pages. - Some leaked stack traces. - No request identifier was included. Root cause analysis took hours because the error surface was inconsistent. This is preventable.What RFC7807 Standardizes
RFC7807 defines a standard JSON structure for HTTP errors. Core fields: - type: a URI identifying the error category - title: short, human-readable summary - status: HTTP status code - detail: human-readable explanation - instance: specific occurrence reference Production systems should extend this with: - errorCode: stable, machine-readable identifier - traceId or requestId - fieldErrors for validation failures The structure must be stable across all endpoints.Anti-Pattern: Returning Raw Exceptions
@ExceptionHandler(Exception.class) public ResponseEntityThis is dangerous because: - Internal class names leak - SQL fragments may appear - File paths and environment hints may leak - Clients receive unstable formats Production rule: Never expose internal exception details in responses.handle(Exception ex) { return ResponseEntity.status(500).body(ex.toString()); }
Correct Pattern: Centralized Global Exception Handler
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.LinkedHashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity
Notice:
- Internal details are not exposed.
- Response shape is consistent.
- Status codes are correct.
- Validation errors are field-level.