NationalSecurityAgency/ghidra · error · IllegalArgumentException
DBAnnotatedField must be non-static and non-final
Error message
DBAnnotatedField must be non-static and non-final
What it means
@DBAnnotatedField marks an instance, mutable column-value field that the factory reads and writes reflectively per row. It therefore cannot be static (no per-instance storage) nor final (cannot be overwritten from a DB record). collectFields rejects both with IllegalArgumentException.
Source
Thrown at Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java:1379
* @param cls the class
* @param fields a map to receive the fields
* @param indexFields a list for receiving fields to be indexed
* @param sparseFields a list for receiving fields to have sparse storage
*/
private static void collectFields(Class<?> cls, Map<String, Field> fields,
List<Field> indexFields, List<Field> sparseFields) {
Class<?> superclass = cls.getSuperclass();
if (superclass != null) {
collectFields(superclass, fields, indexFields, sparseFields);
}
for (Field f : cls.getDeclaredFields()) {
DBAnnotatedField annotation = f.getAnnotation(DBAnnotatedField.class);
if (annotation == null) {
continue;
}
int mod = f.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
throw new IllegalArgumentException(
DBAnnotatedField.class.getSimpleName() + " must be non-static and non-final");
}
f.setAccessible(true);
Field old = fields.put(annotation.column(), f);
if (old != null) {
indexFields.remove(old);
}
if (annotation.indexed()) {
indexFields.add(f);
}
if (annotation.sparse()) {
sparseFields.add(f);
}
}
}
private final DBHandle handle;
private final DBCachedDomainObjectAdapter adapter;View on GitHub (pinned to d5f144c24d)
Solutions
- Remove both `static` and `final` from the annotated field.
- If you actually wanted a static column handle, use @DBAnnotatedColumn instead.
- Re-run the store open to confirm collection succeeds.
Example fix
// before @DBAnnotatedField(column="name") final String name; // after @DBAnnotatedField(column="name") String name;
Defensive patterns
Strategy: validation
Validate before calling
for (Field f : objectType.getDeclaredFields()) {
DBAnnotatedField a = f.getAnnotation(DBAnnotatedField.class);
if (a == None) continue;
int mod = f.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
throw new IllegalStateException("@DBAnnotatedField must be non-static non-final: " + f);
}
} Prevention
- Never mark @DBAnnotatedField fields static or final.
- If immutability is desired, manage it via accessors rather than `final`.
When it happens
Trigger: A field annotated @DBAnnotatedField that carries the `static` or `final` modifier (e.g. `@DBAnnotatedField(column="x") final String name;` or a `static` shared field).
Common situations: Marking a field `final` for an immutability style; sharing a value via `static`; generated/Lombok code that adds final; confusing the value field with a static @DBAnnotatedColumn handle.
Related errors
- @DBAnnotatedColumn fields must be static. Got {}
- @DBAnnotatedColumn fields must be DBObjectColumn type. Got {
- Given field does not apply to given object type
- Given field does not have the given type: {} != {}
- Cannot find column '{}' for @DBAnnotatedColumn on {}
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/2f3c82c20d67f416.
Report an issue: GitHub.