๐Ÿ”ด The Error You're Seeing

Confirm this matches your console output. If it does, you're in the right place.

ERROR LOGorg.springframework.security.access.prepost.PreInvocationExceptionAdvice ... Caused by: java.lang.IllegalArgumentException: Failed to evaluate expression 'hasRole('ADMIN')' at org.springframework.security.access.expression.method.MethodSecurityExpressionRoot.hasRole(MethodSecurityExpressionRoot.java:245) Caused by: org.springframework.expression.spel.SpelEvaluationException ...

โšก Quick Fix Works 80% of the time

Add @EnableMethodSecurity to your SecurityConfig class.

@Configuration @EnableMethodSecurity public class SecurityConfig { ... }

๐Ÿง  Why this Happens

Tap to expand the deep technical explanation

You used `@PreAuthorize` on a controller method, but Spring's method security engine is not turned on. In Spring Security 6, method security is disabled by default. Without the `@EnableMethodSecurity` annotation, Spring ignores `@PreAuthorize` or fails to evaluate the SpEL expression because the security root isn't initialized.

The HITEC City Parking Spot Analogy:

Imagine installing a fancy smart lock (@PreAuthorize) on your office door, but you forgot to connect it to the building's electricity (@EnableMethodSecurity). When someone tries to scan their badge, the lock throws an error because it has no power to evaluate the scan.

๐Ÿ” How to Reproduce Confirm this is your error

Create a SecurityConfig class. Do NOT add `@EnableMethodSecurity`. Add `@PreAuthorize("hasRole('ADMIN')")` to a controller method. Call the endpoint.

๐Ÿ› ๏ธ Solutions (5 Ways to Fix)

Solution 1โœ“ Most common cause

Add @EnableMethodSecurity annotation

๐Ÿ‘‰ Use this as the primary fix when using @PreAuthorize or @PostAuthorize.

This annotation activates the AOP proxy that intercepts method calls and evaluates the security expressions.

@Configuration @EnableMethodSecurity // This replaces @EnableGlobalMethodSecurity from SB2 public class SecurityConfig { ... }
Solution 2

Fix SpEL Syntax Errors

๐Ÿ‘‰ Use this if @EnableMethodSecurity is present but the error persists.

Ensure the expression string has correct quotes and parentheses. SpEL is very strict.

// BAD: missing quotes around ADMIN // @PreAuthorize("hasRole(ADMIN)") // GOOD @PreAuthorize("hasRole('ADMIN')")
Solution 3

Handle Nulls in SpEL

๐Ÿ‘‰ Use this if your expression accesses method parameters that might be null.

If you use `#order.owner`, and `#order` is null, SpEL throws an error. Use the safe navigation operator `?.`.

// BAD: throws error if #order is null // @PreAuthorize("#order.owner == authentication.name") // GOOD: safe navigation @PreAuthorize("#order?.owner == authentication.name")
Solution 4

Ensure the method is public

๐Ÿ‘‰ Use this if your annotation is on a private or protected method.

Spring AOP proxies only intercept public methods. If you put @PreAuthorize on a private method, it won't be evaluated and might throw weird context errors.

@PreAuthorize("hasRole('ADMIN')") public void deleteUser(Long id) { ... } // MUST be public
Solution 5

Use @PreAuthorize on interface or class level correctly

๐Ÿ‘‰ Use this if you want to secure an entire class.

Ensure you aren't overriding a secured method with an unsecured one in a subclass, which confuses the proxy.

@RestController @PreAuthorize("hasRole('ADMIN')") // Secures all methods in class public class AdminController { ... }

๐Ÿ“‹ Version Notes

Spring Boot 2.x

Uses `@EnableGlobalMethodSecurity(prePostEnabled = true)`.

Spring Boot 3.x

Uses `@EnableMethodSecurity` (prePostEnabled is true by default).

๐Ÿ›ก๏ธ How to Prevent This Next Time

Always add `@EnableMethodSecurity` to your SecurityConfig the moment you add the Spring Security dependency, so it's ready when you need it.

Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase