skip to content

What is the ErrorAttributes abstraction in reactive Spring, and how does DefaultErrorAttributes participate in the error response?

level: middleimportance: should knowfreq 45%

answer

  1. getErrorAttributes(request, options) -> Map
  2. DefaultErrorAttributes stores + produces
  3. Options = MESSAGE/BINDING_ERRORS/STACK_TRACE/EXCEPTION
  4. Extend DefaultErrorAttributes to reshape body
  5. Feeds global handler only, not @ExceptionHandler

basics

~20 s

ErrorAttributes is an interface that produces the map of fields (status, error, message, path, timestamp...) used to build the error response body. DefaultErrorAttributes is Boot's implementation; it also stores the exception so the error handler can read it. Extend it to customize the fields.

solid answer

~40 s

`ErrorAttributes` is the Spring Boot contract that turns an exception into the data used for the error response. Its key method is `Map<String,Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options)` — the `options` control whether optional fields (message, stacktrace, binding errors) are included, driven by `server.error.*` properties. `DefaultErrorAttributes` is the default reactive implementation: it also implements the plumbing that **stores** the thrown exception into the exchange attributes (via `storeErrorInformation`), so the `ErrorWebExceptionHandler` can later retrieve it (`getError(ServerRequest)`). The default map includes `timestamp`, `path`, `status`, `error`, `requestId`, and conditionally `message`, `errors`, `trace`. To customize the body without touching rendering, register a bean that extends `DefaultErrorAttributes` and overrides `getErrorAttributes` (call `super`, then add/remove keys). `DefaultErrorWebExceptionHandler` picks up whichever `ErrorAttributes` bean is present.

code

java · 14 lines
java
@Component
public class ApiErrorAttributes extends DefaultErrorAttributes {

    @Override
    public Map<String, Object> getErrorAttributes(ServerRequest request,
                                                  ErrorAttributeOptions options) {
        Map<String, Object> attrs = super.getErrorAttributes(request, options);
        Throwable error = getError(request); // original exception
        attrs.put("errorCode", (error instanceof BusinessException be)
                ? be.getCode() : "INTERNAL");
        attrs.remove("trace"); // defense in depth: never leak stacktrace
        return attrs;
    }
}

go deeper

for a junior

Know it's the source of the default error body fields (status, error, path, timestamp).

for a middle

Explain the options-driven includes and extending DefaultErrorAttributes.

for a senior

Connect it to the global handler path and the leak-prevention properties.

for a principal

Standardize an org error schema via a shared ErrorAttributes and govern info-leak includes.

## The interface ```java public interface ErrorAttributes { Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options); Throwable getError(ServerRequest request); void storeErrorInformation(Throwable error, ServerWebExchange exchange); } ``` (The reactive variant lives in `org.springframework.boot.web.reactive.error`.) It is a **Spring Boot** abstraction — the seam between "an exception happened" and "here is the structured data for the response body." ## DefaultErrorAttributes Boot's default implementation does two jobs: 1. **Store**: `storeErrorInformation(Throwable, ServerWebExchange)` saves the exception in the exchange's attributes. In the reactive stack `DefaultErrorAttributes` is itself wired so the error can be recovered later — the `AbstractErrorWebExceptionHandler` retrieves it via `errorAttributes.getError(request)`. 2. **Produce**: `getErrorAttributes(request, options)` returns the map. Default keys: - `timestamp` — when the error was captured. - `path` — request path. - `status` — numeric HTTP status (from `ResponseStatusException`/`@ResponseStatus`, else 500). - `error` — reason phrase (e.g., "Internal Server Error"). - `requestId` — the exchange's request id. - `message` — exception message (only if included). - `errors` — `BindingResult`/validation errors (only if included). - `trace` — stacktrace string (only if included). ## ErrorAttributeOptions `ErrorAttributeOptions` is a value object listing which optional `Include`s are on: `MESSAGE`, `BINDING_ERRORS`, `STACK_TRACE`, `EXCEPTION`. `DefaultErrorWebExceptionHandler` builds it from the `server.error.include-*` properties (with `on-param` letting a `?trace=true`/`?message=true` query toggle it). This is how you avoid leaking stacktraces by default. ## Customizing The idiomatic, low-risk customization is to extend `DefaultErrorAttributes`: ```java @Component public class ApiErrorAttributes extends DefaultErrorAttributes { @Override public Map<String,Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) { Map<String,Object> attrs = super.getErrorAttributes(request, options); attrs.remove("trace"); // never expose attrs.put("errorCode", deriveCode(getError(request))); return attrs; } } ``` Because `DefaultErrorWebExceptionHandler` renders from the `ErrorAttributes` bean, this reshapes every fallback error body — including those from filters and functional endpoints — consistently. ## Gotchas - `getError(request)` returns the original throwable; use it to branch on exception type when adding fields. - `ErrorAttributes` only feeds the **global** error handler path. It does NOT affect responses produced by your own `@ExceptionHandler` methods — those build their own body. - Keep the map serialization-friendly (plain values); it is written by the configured `HttpMessageWriter`s (usually Jackson). - Don't put secrets/PII in the map; it goes straight to the client. - The `EXCEPTION` include adds the exception class name — also an information-leak risk in production.

  • How do server.error.include-* properties relate to ErrorAttributes?
    They configure the ErrorAttributeOptions the global handler passes to getErrorAttributes, deciding whether message, binding errors, stacktrace, and exception class are added to the map.
  • Does customizing ErrorAttributes change what an @ExceptionHandler returns?
    No. ErrorAttributes only feeds the global DefaultErrorWebExceptionHandler path. @ExceptionHandler methods construct their own response bodies independently.

saying these in an interview costs you the question

  • Thinking ErrorAttributes customizes @ExceptionHandler responses
  • Enabling STACK_TRACE/EXCEPTION includes in production
  • Forgetting to call super.getErrorAttributes and losing the standard fields

context