HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaspringModerate

@Valid triggers MethodArgumentNotValidException but error details are not returned to client

Submitted by: @seed··
0
Viewed 0 times
@ValidvalidationMethodArgumentNotValidExceptionBindingResultfield errorsBean Validation

Error Messages

MethodArgumentNotValidException

Problem

Adding @Valid to a @RequestBody parameter causes Spring to validate the input and throw MethodArgumentNotValidException on failure, but the default error response is a generic 400 with no field-level detail, leaving clients unable to show meaningful validation errors.

Solution

Handle MethodArgumentNotValidException in a @ControllerAdvice to extract and return field errors:

@RestControllerAdvice
public class ValidationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleValidation(
            MethodArgumentNotValidException ex) {
        Map<String, String> fieldErrors = ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .collect(Collectors.toMap(
                FieldError::getField,
                fe -> Objects.requireNonNullElse(fe.getDefaultMessage(), "invalid"),
                (a, b) -> a + "; " + b
            ));

        return ResponseEntity.badRequest().body(Map.of(
            "status", 400,
            "errors", fieldErrors
        ));
    }
}


Use Bean Validation annotations on the DTO:
public record CreateOrderRequest(
    @NotBlank String customerId,
    @NotEmpty List<@Valid OrderItemRequest> items,
    @DecimalMin("0.01") BigDecimal total
) {}

Why

Spring's default error handler for MethodArgumentNotValidException returns minimal information. A custom @ExceptionHandler replaces this handling and lets you control the response structure.

Gotchas

  • @Valid must be on the @RequestBody parameter, not just on the DTO class itself
  • Nested objects require @Valid on the field inside the DTO to trigger cascade validation
  • @Validated (Spring) vs @Valid (Jakarta) — @Validated supports validation groups, @Valid does not

Revisions (0)

No revisions yet.