quarkusio/quarkus · error · IllegalArgumentException
Expression: '<expression>' in the @PreAuthorize annotation o
Error message
Expression: '<expression>' in the @PreAuthorize annotation on method '<method>' of class '<class>' is malformed
What it means
HasRoleValueUtil parses the hasRole(...) argument of @PreAuthorize. Valid forms are a quoted literal ('ROLE_ADMIN') or a bean-field reference (@configBean.someField). If the expression is neither (e.g. starts with @ but does not match @bean.field, or is an unsupported form), SpringSecurityProcessorUtil.createGenericMalformedException throws this IllegalArgumentException at build time.
Source
Thrown at extensions/spring-security/deployment/src/main/java/io/quarkus/spring/security/deployment/HasRoleValueUtil.java:37
private static final String BEAN_FIELD_REGEX = "@(\\w+)\\.(\\w+)";
private static final Pattern BEAN_FIELD_PATTERN = Pattern.compile(BEAN_FIELD_REGEX);
private HasRoleValueUtil() {
}
static Supplier<String[]> getHasRoleValueProducer(String hasRoleValue, MethodInfo methodInfo,
IndexView index,
Map<String, DotName> springBeansNameToDotName,
Map<String, ClassInfo> springBeansNameToClassInfo,
Set<String> beansReferencedInPreAuthorized,
SpringSecurityRecorder recorder) {
if (hasRoleValue.startsWith("'") && hasRoleValue.endsWith("'")) {
return recorder.staticHasRole(hasRoleValue.replace("'", ""));
} else if (hasRoleValue.startsWith("@")) {
Matcher beanFieldMatcher = BEAN_FIELD_PATTERN.matcher(hasRoleValue);
if (!beanFieldMatcher.find()) {
throw SpringSecurityProcessorUtil.createGenericMalformedException(methodInfo, hasRoleValue);
}
String beanName = beanFieldMatcher.group(1);
ClassInfo beanClassInfo = SpringSecurityProcessorUtil.getClassInfoFromBeanName(beanName, index,
springBeansNameToDotName, springBeansNameToClassInfo, hasRoleValue, methodInfo);
String fieldName = beanFieldMatcher.group(2);
FieldInfo fieldInfo = beanClassInfo.field(fieldName);
//TODO: detect normal scoped beans and throw an exception, as it will read the field from the proxy
if ((fieldInfo == null) || !Modifier.isPublic(fieldInfo.flags())
|| !DotNames.STRING.equals(fieldInfo.type().name())) {
throw new IllegalArgumentException("Bean named '" + beanName + "' found in expression '" + hasRoleValue
+ "' in the @PreAuthorize annotation on method " + methodInfo.name() + " of class "
+ methodInfo.declaringClass() + " does not have a public field named '" + fieldName
+ "' of type String");
}
beansReferencedInPreAuthorized.add(fieldInfo.declaringClass().name().toString());View on GitHub (pinned to e1c734241f)
Solutions
- Wrap the role literal in single quotes: hasRole('ROLE_ADMIN')
- If the role comes from configuration, use the @bean.field form: hasRole(@rolesConfig.adminRole) with a public String field
- Simplify the expression — only literal or bean-field forms are supported; move complex logic into a bean method invoked as the whole @PreAuthorize expression
Example fix
// before
@PreAuthorize("hasRole(@roleResolver.getRole())")
// after
@PreAuthorize("hasRole(@rolesConfig.userRole)") // public String userRole field on the config bean Defensive patterns
Strategy: validation
Validate before calling
String v = "'ROLE_ADMIN'"; // or "@config.role"
boolean valid = (v.startsWith("'") && v.endsWith("'"))
|| (v.startsWith("@") && v.matches("@\\w+\\.\\w+"));
if (!valid) throw new IllegalArgumentException("Unsupported hasRole value: " + v); Prevention
- Always single-quote role literals inside hasRole(...)
- Use only the @bean.field form for dynamic role names
- Consult the Quarkus Spring Security guide for the supported expression subset before porting Spring expressions
When it happens
Trigger: getHasRoleValueProducer is given a hasRole value that is not wrapped in single quotes and does not match the regex @(\w+)\.(\w+) — e.g. @beanName.method(), hasRole with double quotes, concatenation, or any other SpEL syntax.
Common situations: Copying full Spring SpEL expressions like hasRole(@resolver.role()) from a Spring Boot app; using double quotes instead of single quotes for the role literal; writing complex expressions the Quarkus Spring Security subset does not support.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Expression: '<part>' in the @PreAuthorize annotation on meth
- Parameter with index <i> of method '<beanMethod>' found in e
- Parameter with index <i> of method '<beanMethod>' found in e
- Could not match a unique method name '<methodName>' for bean
- Could not find a public, boolean returning method named '<me
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/840d1d5796567004.
Report an issue: GitHub.