When users send wrong data, we want to tell them clearly what is wrong. Formatting validation error responses helps users fix their mistakes easily.
Validation error response formatting in Spring Boot
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.Map; import java.util.HashMap; @RestControllerAdvice public class ValidationExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ValidationErrorResponse> handleValidationExceptions(MethodArgumentNotValidException ex) { ValidationErrorResponse errors = new ValidationErrorResponse(); ex.getBindingResult().getFieldErrors().forEach(error -> { String fieldName = error.getField(); String errorMessage = error.getDefaultMessage(); errors.addError(fieldName, errorMessage); }); return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); } } class ValidationErrorResponse { private Map<String, String> errors = new HashMap<>(); public void addError(String field, String message) { errors.put(field, message); } public Map<String, String> getErrors() { return errors; } }
This code uses @RestControllerAdvice to catch validation errors globally.
The MethodArgumentNotValidException contains details about which fields failed validation.
@ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage()) ); return ResponseEntity.badRequest().body(errors); }
public record ValidationError(String field, String message) {}
public record ValidationErrorResponse(List<ValidationError> errors) {}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ValidationErrorResponse> handleValidationExceptions(MethodArgumentNotValidException ex) {
List<ValidationError> errorList = ex.getBindingResult().getFieldErrors().stream()
.map(error -> new ValidationError(error.getField(), error.getDefaultMessage()))
.toList();
return ResponseEntity.badRequest().body(new ValidationErrorResponse(errorList));
}This Spring Boot app has a UserController that accepts a user with a name. The name must not be blank.
If the user sends an empty name, the ValidationExceptionHandler catches the error and returns a JSON with the field and message.
package com.example.demo; import jakarta.validation.constraints.NotBlank; import jakarta.validation.Valid; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } @RestController @RequestMapping("/users") class UserController { @PostMapping public String createUser(@RequestBody @Valid User user) { return "User created: " + user.name(); } } record User(@NotBlank(message = "Name must not be blank") String name) {} @RestControllerAdvice class ValidationExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); for (FieldError error : ex.getBindingResult().getFieldErrors()) { errors.put(error.getField(), error.getDefaultMessage()); } return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); } }
Always use @Valid on method parameters to trigger validation.
Customize error messages in your validation annotations for clearer feedback.
Return HTTP 400 (Bad Request) status for validation errors to follow web standards.
Validation error formatting helps users understand what went wrong.
Use @RestControllerAdvice and @ExceptionHandler to catch and format errors globally.
Return clear JSON with field names and error messages for easy frontend use.