Learnitweb

Custom error message when validation fails

To make your Spring Boot REST API return custom error messages when validation fails, you need to:

  1. Use Bean Validation annotations like @NotNull, @Size, etc.
  2. Handle validation errors using a custom @ControllerAdvice class that captures and formats those errors.

Step-by-Step Guide

Step 1: Add Validation Dependency

If you’re using Maven, make sure you have this in your pom.xml:

<dependency>
    <groupId>jakarta.validation</groupId>
    <artifactId>jakarta.validation-api</artifactId>
</dependency>

Or for older versions:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Step 2: Annotate Your Request DTO

Example DTO with validation annotations:

public class UserRequest {
    
    @NotBlank(message = "Name must not be blank")
    private String name;

    @Email(message = "Invalid email format")
    private String email;

    @Min(value = 18, message = "Age must be at least 18")
    private int age;

    // Getters and Setters
}

Step 3: Use @Valid in Your Controller

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping
    public ResponseEntity<String> createUser(@Valid @RequestBody UserRequest userRequest) {
        // your logic here
        return ResponseEntity.ok("User created");
    }
}

Step 4: Create a Global Exception Handler

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleValidationErrors(MethodArgumentNotValidException ex) {
        Map<String, Object> errors = new LinkedHashMap<>();
        errors.put("timestamp", LocalDateTime.now());
        errors.put("status", HttpStatus.BAD_REQUEST.value());

        List<String> validationErrors = ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(error -> error.getField() + ": " + error.getDefaultMessage())
            .collect(Collectors.toList());

        errors.put("errors", validationErrors);
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }
}

Sample JSON Response on Validation Error:

{
  "timestamp": "2025-09-26T20:00:00",
  "status": 400,
  "errors": [
    "email: Invalid email format",
    "age: Age must be at least 18"
  ]
}

Optional: Customize Further

You can create a fully custom response object:

public class ErrorResponse {
    private String message;
    private List<String> details;

    public ErrorResponse(String message, List<String> details) {
        this.message = message;
        this.details = details;
    }

    // Getters and setters
}

And return it like this:

ErrorResponse errorResponse = new ErrorResponse("Validation Failed", validationErrors);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);