Spring Boot
Exception Handling
RestController
ControllerAdvice
Java

ControllerAdvice and ExceptionHandler not getting triggered for my RestController

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When @ControllerAdvice and @ExceptionHandler do not trigger for a Spring @RestController, the root issue is usually scanning scope, exception type mismatch, or handler ordering. This problem is common in modular projects where advice classes are outside component scan packages.

This article gives a focused debugging workflow.

Core Sections

1) Minimal global handler setup

java
1@RestControllerAdvice
2public class ApiExceptionHandler {
3
4    @ExceptionHandler(IllegalArgumentException.class)
5    public ResponseEntity<String> handleIllegalArg(IllegalArgumentException ex) {
6        return ResponseEntity.badRequest().body(ex.getMessage());
7    }
8}

@RestControllerAdvice combines @ControllerAdvice + @ResponseBody semantics.

2) Ensure package scanning includes advice

If advice class sits outside the base package of @SpringBootApplication, it may never register.

java
@SpringBootApplication(scanBasePackages = {"com.example.api", "com.example.shared"})

3) Match thrown exception type

If controller wraps exceptions or converts them, your handler may not match.

java
throw new IllegalArgumentException("invalid input");

Verify actual exception class in logs.

4) Handler precedence and fallback

Add broad fallback handler after specific ones.

java
1@ExceptionHandler(Exception.class)
2public ResponseEntity<String> handleGeneric(Exception ex) {
3    return ResponseEntity.status(500).body("unexpected");
4}

5) Validation exceptions

Bean validation errors often use different exception types (MethodArgumentNotValidException) and need dedicated handlers.

6) Production checklist for Spring global exception routing

A correct code snippet is only the baseline. To make this approach durable in production, define explicit acceptance checks around correctness, reliability, and operational behavior. Correctness means the output should match known-good fixtures for both normal and edge-case inputs. Reliability means failures are predictable and observable, with clear error messages and no silent degradation paths. Operational behavior means the implementation performs within expected latency and resource usage under realistic load, not only under tiny test data. Teams that skip this validation layer often ship logic that appears correct in local testing but fails under real traffic or environmental differences.

Document assumptions near the implementation: runtime version, dependency versions, required environment variables, and external system expectations. Many regressions are caused by version drift or configuration changes, not by algorithmic mistakes. If this workflow depends on filesystem paths, network resources, security credentials, or framework defaults, codify those requirements in code comments or adjacent documentation so they are visible during review. Add one deterministic smoke test that executes this path end-to-end and one failure-mode test that proves errors are surfaced with enough context for quick triage.

A practical release sequence is:

  1. Run static checks and unit tests in CI.
  2. Execute a smoke test with representative input shape and size.
  3. Trigger one expected failure mode and verify logs/metrics.
  4. Deploy with staged rollout or feature flag where possible.
  5. Monitor stabilization metrics before broad rollout.
bash
1# Example delivery workflow
2make lint
3make test
4./scripts/smoke_check.sh

Ownership and rollback should also be explicit. Define who responds when this component fails, what thresholds trigger rollback, and which fallback behavior is acceptable for users. If the workflow is business-critical, keep a concise runbook that includes common failure signatures and first-response steps. This reduces mean time to recovery and prevents repeated rediscovery of the same diagnostics.

Finally, maintain a brief limitations note. State what this approach intentionally does not solve and where alternative patterns are preferred. This prevents accidental overuse and keeps architecture decisions grounded in explicit tradeoffs. Revisit this checklist after framework, runtime, or infrastructure upgrades because previously safe assumptions can change when defaults evolve.

Common Pitfalls

  • Placing advice class outside component scan scope.
  • Handling wrong exception class while real exception differs.
  • Using @ControllerAdvice but expecting JSON body without @ResponseBody.
  • Registering conflicting handlers in multiple advice classes without order control.
  • Ignoring framework-generated exceptions from validation and binding.

Summary

If global exception handlers do not fire, first verify advice registration, then confirm exception type mapping, then add specific handlers for validation/binding flows. Most failures are configuration mismatch, not Spring framework bugs.


Course illustration
Course illustration

All Rights Reserved.