Spring Boot
REST API
Validation
Error Handling
Java

Spring boot REST validation error response

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Validation in a Spring Boot REST API is only half the job. The other half is turning validation failures into a response shape that clients can rely on instead of exposing a noisy default exception payload.

Triggering Validation on Request Bodies

For JSON request payloads, the usual pattern is Bean Validation plus @Valid on the controller method parameter.

java
1package com.example.demo;
2
3import jakarta.validation.constraints.Email;
4import jakarta.validation.constraints.NotBlank;
5
6public record CreateUserRequest(
7    @NotBlank(message = "name is required")
8    String name,
9
10    @Email(message = "email must be valid")
11    @NotBlank(message = "email is required")
12    String email
13) {
14}

Then in the controller:

java
1package com.example.demo;
2
3import jakarta.validation.Valid;
4import org.springframework.http.HttpStatus;
5import org.springframework.web.bind.annotation.PostMapping;
6import org.springframework.web.bind.annotation.RequestBody;
7import org.springframework.web.bind.annotation.ResponseStatus;
8import org.springframework.web.bind.annotation.RestController;
9
10@RestController
11public class UserController {
12
13    @PostMapping("/users")
14    @ResponseStatus(HttpStatus.CREATED)
15    public CreateUserRequest create(@Valid @RequestBody CreateUserRequest request) {
16        return request;
17    }
18}

If the JSON is invalid, Spring MVC raises MethodArgumentNotValidException for that request body.

Why the Default Error Response Is Often Not Enough

Spring Boot can already return an error response when validation fails, but the default structure is not always ideal for public APIs. Clients usually need something stable and small, such as:

  • a top-level error code
  • a human-readable message
  • field-specific validation errors

That is why most APIs add a global exception handler.

Build a Consistent Error Payload

Start with simple response records:

java
1package com.example.demo;
2
3import java.util.List;
4
5public record ValidationErrorResponse(
6    String code,
7    String message,
8    List<FieldViolation> violations
9) {
10}
11
12record FieldViolation(String field, String message) {
13}

Then map the exception in a @RestControllerAdvice:

java
1package com.example.demo;
2
3import java.util.List;
4import org.springframework.http.HttpStatus;
5import org.springframework.http.ResponseEntity;
6import org.springframework.web.bind.MethodArgumentNotValidException;
7import org.springframework.web.bind.annotation.ExceptionHandler;
8import org.springframework.web.bind.annotation.RestControllerAdvice;
9
10@RestControllerAdvice
11public class ApiExceptionHandler {
12
13    @ExceptionHandler(MethodArgumentNotValidException.class)
14    public ResponseEntity<ValidationErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
15        List<FieldViolation> violations = ex.getBindingResult()
16            .getFieldErrors()
17            .stream()
18            .map(error -> new FieldViolation(error.getField(), error.getDefaultMessage()))
19            .toList();
20
21        ValidationErrorResponse body = new ValidationErrorResponse(
22            "VALIDATION_ERROR",
23            "Request validation failed",
24            violations
25        );
26
27        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(body);
28    }
29}

Now the client gets a stable contract rather than a framework-specific blob.

Example Response

For a request such as:

json
1{
2  "name": "",
3  "email": "not-an-email"
4}

The API can return:

json
1{
2  "code": "VALIDATION_ERROR",
3  "message": "Request validation failed",
4  "violations": [
5    { "field": "name", "message": "name is required" },
6    { "field": "email", "message": "email must be valid" }
7  ]
8}

That format is easier for front-end code and other API consumers to process consistently.

Validation Beyond Request Bodies

Spring also supports method and parameter validation. For example, path variables and query parameters can use constraints when the controller is annotated with @Validated.

java
1package com.example.demo;
2
3import jakarta.validation.constraints.Min;
4import org.springframework.validation.annotation.Validated;
5import org.springframework.web.bind.annotation.GetMapping;
6import org.springframework.web.bind.annotation.RequestParam;
7import org.springframework.web.bind.annotation.RestController;
8
9@RestController
10@Validated
11public class SearchController {
12
13    @GetMapping("/search")
14    public String search(@RequestParam @Min(1) int page) {
15        return "page=" + page;
16    }
17}

Recent Spring versions may raise HandlerMethodValidationException for those method-parameter cases, not just MethodArgumentNotValidException. If your API uses both body validation and parameter validation, handle both deliberately.

Practical Design Advice

A good validation error response should be:

  • stable across endpoints
  • small enough for clients to parse easily
  • specific enough to tell the caller which fields failed
  • decoupled from internal exception class names

Do not leak framework internals into the public API contract unless that is a conscious choice.

Common Pitfalls

The most common mistake is using @Valid and stopping there, then discovering later that the default response shape is inconsistent with the rest of the API.

Another mistake is returning only a generic "Bad Request" message. Clients need field-level detail if they are expected to fix the request programmatically or show accurate form messages.

Developers also often handle only MethodArgumentNotValidException and forget method-level validation failures on query parameters or path variables.

Finally, keep the response schema stable. Changing the validation error format between endpoints makes client code harder than it needs to be.

Summary

  • Use Bean Validation annotations and @Valid to trigger request-body validation in Spring Boot.
  • Catch MethodArgumentNotValidException in a @RestControllerAdvice to shape a consistent API response.
  • Include field names and messages so clients can react intelligently.
  • If you validate query or path parameters, also consider HandlerMethodValidationException.
  • Treat validation errors as part of the API contract, not just as thrown exceptions.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.