{"record":{"id":"2f3c82c20d67f416","repo":"NationalSecurityAgency/ghidra","slug":"dbannotatedfield-must-be-non-static-and-non-final","errorCode":null,"errorMessage":"DBAnnotatedField must be non-static and non-final","messagePattern":"DBAnnotatedField must be non-static and non-final","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java","lineNumber":1379,"sourceCode":"\t * @param cls the class\n\t * @param fields a map to receive the fields\n\t * @param indexFields a list for receiving fields to be indexed\n\t * @param sparseFields a list for receiving fields to have sparse storage\n\t */\n\tprivate static void collectFields(Class<?> cls, Map<String, Field> fields,\n\t\t\tList<Field> indexFields, List<Field> sparseFields) {\n\t\tClass<?> superclass = cls.getSuperclass();\n\t\tif (superclass != null) {\n\t\t\tcollectFields(superclass, fields, indexFields, sparseFields);\n\t\t}\n\t\tfor (Field f : cls.getDeclaredFields()) {\n\t\t\tDBAnnotatedField annotation = f.getAnnotation(DBAnnotatedField.class);\n\t\t\tif (annotation == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint mod = f.getModifiers();\n\t\t\tif (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\tDBAnnotatedField.class.getSimpleName() + \" must be non-static and non-final\");\n\t\t\t}\n\t\t\tf.setAccessible(true);\n\t\t\tField old = fields.put(annotation.column(), f);\n\t\t\tif (old != null) {\n\t\t\t\tindexFields.remove(old);\n\t\t\t}\n\t\t\tif (annotation.indexed()) {\n\t\t\t\tindexFields.add(f);\n\t\t\t}\n\t\t\tif (annotation.sparse()) {\n\t\t\t\tsparseFields.add(f);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate final DBHandle handle;\n\tprivate final DBCachedDomainObjectAdapter adapter;","sourceCodeStart":1361,"sourceCodeEnd":1397,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java#L1361-L1397","documentation":"@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.","triggerScenarios":"A field annotated @DBAnnotatedField that carries the `static` or `final` modifier (e.g. `@DBAnnotatedField(column=\"x\") final String name;` or a `static` shared field).","commonSituations":"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.","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."],"exampleFix":"// before\n@DBAnnotatedField(column=\"name\")\nfinal String name;\n// after\n@DBAnnotatedField(column=\"name\")\nString name;","handlingStrategy":"validation","validationCode":"for (Field f : objectType.getDeclaredFields()) {\n    DBAnnotatedField a = f.getAnnotation(DBAnnotatedField.class);\n    if (a == None) continue;\n    int mod = f.getModifiers();\n    if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {\n        throw new IllegalStateException(\"@DBAnnotatedField must be non-static non-final: \" + f);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never mark @DBAnnotatedField fields static or final.","If immutability is desired, manage it via accessors rather than `final`."],"tags":["database","annotation","reflection"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}