After upgrading to Spring Boot version 3.3.2, I've noticed that the getErrorAttributes method from DefaultErrorAttributes is being executed twice for a single request. This behavior differs from version 3.3.0, where getErrorAttributes was executed only once.

Steps to Reproduce:

  • Define the following Spring Boot configuration and classes:
public interface ExceptionHandlerCustomizer<T extends Throwable> {
    boolean supports(Throwable throwable);

    void customize(Map<String, Object> errorAttributes, T throwable);
}
@Slf4j
@RequiredArgsConstructor
public class ExceptionAttributesWrapper extends DefaultErrorAttributes {
    private final List<ExceptionHandlerCustomizer> handlerCustomizers;

    @Override
    public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
        final var error = getError(request);
        final var errorAttributes = super.getErrorAttributes(request, options);

        handlerCustomizers.stream()
                          .filter(handler -> handler.supports(error))
                          .forEach(handler -> handler.customize(errorAttributes, error));

        return errorAttributes;
    }

    @Getter
    public enum ErrorAttribute {
        STATUS("status"),
        ERROR("error"),
        ERROR_CODE("errorCode"),
        DEVELOPER_MESSAGE("developerMessage"),
        USER_MESSAGE("userMessage"),
        VALIDATION_DETAILS("validationDetails"),
        SOURCE_APP("sourceApp");

        private final String value;

        ErrorAttribute(String value) {
            this.value = value;
        }

    }

}
@Configuration(proxyBeanMethods = false)
public class HttpExceptionHandlerConfiguration {

    @Bean
    ExceptionHandlerCustomizer<ConstraintViolationException> constraintViolationExceptionHandler() {
        return new ConstraintViolationExceptionHandlerCustomizer();
    }

    @SuppressWarnings("rawtypes")
    @Bean
    ErrorAttributes errorAttributes(List<ExceptionHandlerCustomizer> handlers) {
        return new ExceptionAttributesWrapper(handlers);
    }
}
@Slf4j
public class ConstraintViolationExceptionHandlerCustomizer implements ExceptionHandlerCustomizer<ConstraintViolationException> {

    @Override
    public boolean supports(Throwable throwable) {
        return ConstraintViolationException.class.isAssignableFrom(throwable.getClass());
    }

    @Override
    public void customize(Map<String, Object> errorAttributes, ConstraintViolationException throwable) {
        String errorName = throwable.getClass().getSimpleName();
        String errorMessage = ExceptionUtils.getRootCause(throwable).getMessage();
        log.debug("Caught an instance of: {}, err: {}", errorName, errorMessage);

        errorAttributes.replace(ExceptionAttributesWrapper.ErrorAttribute.STATUS.getValue(), 400);
        errorAttributes.put(ExceptionAttributesWrapper.ErrorAttribute.ERROR.getValue(), errorName);
        errorAttributes.put(ExceptionAttributesWrapper.ErrorAttribute.DEVELOPER_MESSAGE.getValue(), errorMessage);
    }

}
    @RequestMapping(
            method = RequestMethod.DELETE,
            value = "/v1/test/pnr/{pnr}/sth/{sth}"
    )
    default Mono<ResponseEntity<Void>> testEndpoint(
            @Size(min = 11, max = 11) @Parameter(name = "pnr", description = "PNR. ", required = true, in = ParameterIn.PATH) @PathVariable("pnr") String pnr,
            @Parameter(name = "sth", description = "Sth. ", required = true, in = ParameterIn.PATH) @PathVariable("sth") String sth
    ) {
        Mono<Void> result = Mono.empty();
        exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED);
        return result.then(Mono.empty());

    }
  • Deploy the application and trigger an error that would be handled by the ConstraintViolationExceptionHandlerCustomizer.
  • Observe the logs. The getErrorAttributes method is logged as being executed twice. SpringBoot getErrorAttributes from DefaultErrorAttributes is executed twice after upgrading to Spring Boot 3.3.2
  • On debug, I can also observe that my breakpoint is being executed twice.

Environment: - Spring Boot Version: 3.3.2 - Java Version: Amazon Coretto 17.0.12

Comment From: philwebb

@bskorka Can you please upgrade to 3.3.3 to see if your issue has been fixed by #41995

Comment From: bskorka

@philwebb — yes, it helps! I updated our Spring Boot version on the morning of August 22nd. The 3.3.3 version was released in the evening of that day. All in all, it works properly now, thank you for that fix, and your input.