Error Handling
When something goes wrong, send the client a clear error and the right status code instead of an ugly stack trace.
What you will learn
- Return the correct HTTP status
- Throw a clean “not found” error
- Handle errors in one central place
Errors should be helpful
If a client asks for a product that does not exist, returning null or a huge Java error is confusing. A good API returns a clear status code and a short message. The status code tells the client what kind of problem it was.
| Status | Means |
|---|---|
| 200 OK | Success |
| 201 Created | A new item was created |
| 400 Bad Request | The client sent invalid data |
| 404 Not Found | The thing does not exist |
| 500 Server Error | Something broke on the server |
Throw a clean 404
Make a small exception class and tell Spring which status it maps to with @ResponseStatus:
@ResponseStatus(HttpStatus.NOT_FOUND) // -> 404
public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
}
@GetMapping("/products/{id}")
public Product one(@PathVariable Long id) {
return repo.findById(id)
.orElseThrow(() -> new NotFoundException("No product with id " + id));
}Note: Output: GET /products/999 (no such product) -> 404 Not Found {"status":404,"error":"No product with id 999", ...} Instead of a crash or a null, the client gets a clean 404 with your message. The status code makes the problem obvious.
Handle errors in one place
For app-wide handling, a @RestControllerAdvice class catches exceptions from all controllers, so you write the handling once:
@RestControllerAdvice
public class ErrorHandler {
@ExceptionHandler(NotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public Map<String, String> handleNotFound(NotFoundException ex) {
return Map.of("error", ex.getMessage());
}
}Note: Output: Any NotFoundException, from any controller: -> 404 Not Found {"error":"No product with id 999"} You wrote the handling once and every controller now returns the same tidy error shape.
Tip: Pick the status that matches the problem: 404 for “not found”, 400 for “bad input”, 201 for “created”. Correct status codes make your API easy and predictable to use.
Watch out: Never send raw Java stack traces to clients — they are confusing and can leak internal details. Catch errors and return a short, friendly message with the right status instead.
Q. Which status code best fits “you asked for an item that does not exist”?
✍️ Practice
- Throw a 404 NotFoundException when a Book id is missing.
- Add a
@RestControllerAdvicehandler that returns a JSON error message for it.
🏠 Homework
- Add proper error handling to your Task CRUD API: 404 for a missing task, with a central handler returning a clean message.