Exception handling in Spring Boot is the mechanism used to manage runtime errors and provide meaningful responses to the client instead of exposing internal errors.
Without proper exception handling:| Type | Description | Example |
|---|---|---|
| Checked Exception | Must be handled at compile time | IOException |
| Unchecked Exception | Occurs at runtime | NullPointerException |
| Custom Exception | User-defined exceptions | ResourceNotFoundException |
Spring Boot automatically provides a Basic Error Controller.
If an exception occurs, Spring Boot returns a default JSON response like:
{
"timestamp": "2026-03-06T10:30:20.123+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/users"
}
This is handled internally by:
| Method | Annotation | Usage |
|---|---|---|
| Method Level | @ExceptionHandler | Handle exceptions inside controller |
| Global Handler | @ControllerAdvice | Handle exceptions globally |
| REST Global Handler | @RestControllerAdvice | Used for REST APIs |
| Custom Exceptions | Extend RuntimeException | Business-specific errors |
This annotation handles exceptions inside a controller class.
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public String getUser(@PathVariable int id) {
if(id == 10) {
throw new RuntimeException("User not found");
}
return "User Found";
}
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleException(RuntimeException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}
}
Client Request
↓
Controller Method
↓
Exception Occurs
↓
@ExceptionHandler Method
↓
Custom Response Returned
@ControllerAdvice allows handling exceptions across multiple controllers globally.
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleRuntimeException(RuntimeException ex) {
return new ResponseEntity<>(
"Error: " + ex.getMessage(),
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
@RestControllerAdvice is similar to @ControllerAdvice
but automatically applies @ResponseBody.
This is ideal for REST APIs.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex) {
return new ResponseEntity<>(
ex.getMessage(),
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
@GetMapping("/{id}")
public String getUser(@PathVariable int id) {
if(id != 1) {
throw new ResourceNotFoundException("User not found with id: " + id);
}
return "User Found";
}
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleResourceNotFound(ResourceNotFoundException ex) {
return new ResponseEntity<>(
ex.getMessage(),
HttpStatus.NOT_FOUND
);
}
}
public class ErrorResponse {
private LocalDateTime timestamp;
private int status;
private String message;
private String path;
}
{
"timestamp": "2026-03-06T10:45:22",
"status": 404,
"message": "User not found with id: 5",
"path": "/users/5"
}
@PostMapping("/users")
public ResponseEntity<String> createUser(@Valid @RequestBody User user) {
return ResponseEntity.ok("User Created");
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String,String>> handleValidationException(
MethodArgumentNotValidException ex) {
Map<String,String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage())
);
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}
{
"email": "Invalid email format",
"name": "Name must not be blank"
}
Client Request
↓
Controller
↓
Service Layer
↓
Exception Thrown
↓
@ControllerAdvice / @RestControllerAdvice
↓
@ExceptionHandler
↓
Error Response Object
↓
HTTP Response to Client
| Concept | Purpose |
|---|---|
| @ExceptionHandler | Handle exceptions inside controller |
| @ControllerAdvice | Global exception handling |
| @RestControllerAdvice | Global REST exception handling |
| Custom Exception | Business logic errors |
| ErrorResponse | Structured error response |
| Validation Handling | Manage input validation errors |