quarkusio/quarkus · error · IllegalArgumentException
Bean named '<beanName>' found in expression '<expression>' i
Error message
Bean named '<beanName>' found in expression '<expression>' in the @PreAuthorize annotation on method <method> of class <class> does not have a public field named '<fieldName>' of type String
What it means
When a hasRole value references a bean field (@beanName.fieldName), Quarkus requires that field to exist, be public, and be of type String, because the generated check reads it directly at runtime. This IllegalArgumentException is thrown at build time when any of these conditions fails.
Source
Thrown at extensions/spring-security/deployment/src/main/java/io/quarkus/spring/security/deployment/HasRoleValueUtil.java:49
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());
return recorder.fromBeanField(fieldInfo.declaringClass().name().toString(), fieldName);
} else {
throw SpringSecurityProcessorUtil.createGenericMalformedException(methodInfo, hasRoleValue);
}
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Make the referenced field public and of type String on the bean class
- Change the expression to reference an existing public String field
- If the value is not a String, convert it (e.g. add a public String field that mirrors the value) or restructure using a bean method check
Example fix
// before
@Component
public class RolesConfig { private String adminRole = "ROLE_ADMIN"; }
@PreAuthorize("hasRole(@rolesConfig.adminRole)")
// after
@Component
public class RolesConfig { public String adminRole = "ROLE_ADMIN"; }
@PreAuthorize("hasRole(@rolesConfig.adminRole)") Defensive patterns
Strategy: validation
Validate before calling
Field f;
try { f = RolesConfig.class.getField("adminRole"); }
catch (NoSuchFieldException e) { throw new IllegalStateException("missing field"); }
if (!java.lang.reflect.Modifier.isPublic(f.getModifiers()) || f.getType() != String.class)
throw new IllegalStateException("field must be public String"); Prevention
- Declare bean fields referenced in hasRole(@bean.field) as public String
- Avoid referencing getters or non-String fields in these expressions
- Keep the config bean and the expression in sync when renaming fields
When it happens
Trigger: getHasRoleValueProducer resolves @beanName.fieldName and the field is absent, non-public (private/protected/package-private), static, or of a type other than java.lang.String (e.g. boolean, List<String>).
Common situations: Referencing a private config field; referencing a constant of non-String type; renaming the field after writing the expression; using a getter-style path (@bean.someProperty) instead of an actual field.
Related errors
- 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
- Expression: '<expression>' in the @PreAuthorize annotation o
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ef03d8cdb252b414.
Report an issue: GitHub.