quarkusio/quarkus · error · DefinitionException
Non-static public field ${field} present on normal scoped be
Error message
Non-static public field ${field} present on normal scoped bean ${beanClass} What it means
With strict CDI compatibility enabled, normal-scoped beans (e.g. @ApplicationScoped) must not declare non-static public fields, because the client proxy would bypass field access semantics. ArC throws this DefinitionException while validating class beans.
Source
Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java:1357
for (ClassInfo beanClass : beanClasses) {
BeanInfo classBean = Beans.createClassBean(beanClass, this, injectionPointTransformer);
if (classBean != null) {
beans.add(classBean);
beanClassToBean.put(beanClass, classBean);
injectionPoints.addAll(classBean.getAllInjectionPoints());
// specification requires to disallow non-static public fields on non-`@Dependent` beans,
// but we do what Weld does: only disallow them on normal scoped beans (disallowing them
// on `@Singleton` beans would actually prevent passing the AtInject TCK)
//
// only check this in the strictly compatible mode, as this is pretty invasive,
// it even prevents public producer fields
if (classBean.getScope().isNormal() && strictCompatibility) {
ClassInfo aClass = beanClass;
while (aClass != null) {
for (FieldInfo field : aClass.fields()) {
if (Modifier.isPublic(field.flags()) && !Modifier.isStatic(field.flags())) {
throw new DefinitionException("Non-static public field " + field
+ " present on normal scoped bean " + beanClass);
}
}
DotName superClass = aClass.superName();
aClass = superClass != null && !superClass.equals(DotNames.OBJECT)
? getClassByName(getBeanArchiveIndex(), superClass)
: null;
}
}
}
}
List<DisposerInfo> disposers = new ArrayList<>();
for (MethodInfo disposerMethod : disposerMethods) {
BeanInfo declaringBean = beanClassToBean.get(disposerMethod.declaringClass());
if (declaringBean != null) {
Injection injection = Injection.forDisposer(disposerMethod, declaringBean.getImplClazz(), this,View on GitHub (pinned to e1c734241f)
Solutions
- Make the field private and add getter/setter accessors.
- Change the bean scope to @Dependent (pseudo-scope) if proxies are not needed.
- Make the field static if it is genuinely constant-like.
- Move the public fields into a separate non-bean POJO.
Example fix
// before
@ApplicationScoped
class Counter {
public int count;
}
// after
@ApplicationScoped
class Counter {
private int count;
public int getCount() { return count; }
} Defensive patterns
Strategy: validation
Validate before calling
// Check a normal-scoped bean class for public non-static fields
static List<Field> offendingFields(Class<?> bean) {
List<Field> bad = new ArrayList<>();
for (Class<?> c = bean; c != null && c != Object.class; c = c.getSuperclass()) {
for (Field f : c.getDeclaredFields()) {
if (Modifier.isPublic(f.getModifiers()) && !Modifier.isStatic(f.getModifiers())) bad.add(f);
}
}
return bad;
} Prevention
- Always use private fields with accessor methods in scoped beans
- Avoid enabling strict-compatibility on legacy code without an audit
- Use @Dependent scope for field-exposed DTO-style beans
When it happens
Trigger: strictCompatibility is on and a class bean with a normal scope has a public non-static field (checked across the whole superclass hierarchy up to Object).
Common situations: Porting an existing CDI/Weld codebase where public fields were tolerated; writing structs/DTO-style beans with @ApplicationScoped; enabling quarkus.arc.strict-compatibility and newly failing existing beans.
Related errors
- Unsupported injection point target: <injectionPoint>
- Method ${method} of class ${beanClass} is not a producer met
- Injected field cannot be annotated with @Produces: ${field}
- Field ${field} of class ${beanClass} is not a producer field
- No producer method or field declared by the bean class that
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/0fd17467ebc761b3.
Report an issue: GitHub.