{"record":{"id":"fccc1272592f9ede","repo":"NationalSecurityAgency/ghidra","slug":"dbannotatedcolumn-fields-must-be-static-got","errorCode":null,"errorMessage":"@DBAnnotatedColumn fields must be static. Got {}","messagePattern":"@DBAnnotatedColumn fields must be static\\. Got (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java","lineNumber":1172,"sourceCode":"\t\t * Initialize the static {@link DBObjectColumn} fields marked with {@link DBAnnotatedColumn}\n\t\t * \n\t\t * @param objectType the clas of objects being described\n\t\t * @param numbersByName the assigned column numbers by user-defined name\n\t\t */\n\t\tvoid writeColumnNumbers(Class<? extends DBAnnotatedObject> objectType,\n\t\t\t\tMap<String, Integer> numbersByName) {\n\t\t\tClass<?> superType = objectType.getSuperclass();\n\t\t\tif (DBAnnotatedObject.class.isAssignableFrom(superType)) {\n\t\t\t\twriteColumnNumbers(superType.asSubclass(DBAnnotatedObject.class), numbersByName);\n\t\t\t}\n\t\t\tfor (Field f : objectType.getDeclaredFields()) {\n\t\t\t\tDBAnnotatedColumn annotation = f.getAnnotation(DBAnnotatedColumn.class);\n\t\t\t\tif (annotation == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tint mod = f.getModifiers();\n\t\t\t\tif (!Modifier.isStatic(mod)) {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"@\" + DBAnnotatedColumn.class.getSimpleName() +\n\t\t\t\t\t\t\t\" fields must be static. Got \" + f);\n\t\t\t\t}\n\t\t\t\tif (f.getType() != DBObjectColumn.class) {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"@\" + DBAnnotatedColumn.class.getSimpleName() + \" fields must be \" +\n\t\t\t\t\t\t\tDBObjectColumn.class.getSimpleName() + \" type. Got \" + f);\n\t\t\t\t}\n\n\t\t\t\tString name = annotation.value();\n\n\t\t\t\tInteger columnNumber = numbersByName.get(name);\n\t\t\t\tif (columnNumber == null) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Cannot find column '\" + name + \"' for @\" +\n\t\t\t\t\t\tDBAnnotatedColumn.class.getSimpleName() + \" on \" + f);\n\t\t\t\t}\n\n\t\t\t\tf.setAccessible(true);","sourceCodeStart":1154,"sourceCodeEnd":1190,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java#L1154-L1190","documentation":"DBCachedObjectStoreFactory.writeColumnNumbers scans every declared field of a DBAnnotatedObject subclass for @DBAnnotatedColumn. That annotation injects a shared DBObjectColumn handle into the class so code can reference a column programmatically. The handle MUST be a static field because it is shared across all rows; an instance field would be re-injected per object and defeat the purpose, so a non-static field is rejected at store-build time with IllegalArgumentException.","triggerScenarios":"A field carrying @DBAnnotatedColumn is declared without the `static` modifier (e.g. `@DBAnnotatedColumn(\"name\") DBObjectColumn NAME;`). The guard is literally `if (!Modifier.isStatic(mod)) throw ...`, hit the first time a store/table is opened for that object type.","commonSituations":"Copying the annotation from a @DBAnnotatedField (instance) field and forgetting `static`; refactoring that drops the modifier; IDE auto-format or codegen that omits it; converting an instance column handle to a class handle.","solutions":["Add the `static` modifier to the annotated field.","Confirm the field is a true class field (static, optionally final) that should hold one DBObjectColumn per type.","If you actually wanted per-row data, switch the annotation to @DBAnnotatedField instead."],"exampleFix":"// before\n@DBAnnotatedColumn(\"name\")\nDBObjectColumn NAME;\n// after\n@DBAnnotatedColumn(\"name\")\nstatic DBObjectColumn NAME;","handlingStrategy":"validation","validationCode":"// Before opening the store, ensure every @DBAnnotatedColumn field is static.\nfor (Field f : objectType.getDeclaredFields()) {\n    if (f.isAnnotationPresent(DBAnnotatedColumn.class) && !Modifier.isStatic(f.getModifiers())) {\n        throw new IllegalStateException(\"Non-static @DBAnnotatedColumn field: \" + f);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep all @DBAnnotatedColumn fields `static` by convention; review during code review.","Add a unit test that reflectively asserts the modifier contract for each DBAnnotatedObject type on startup."],"tags":["database","annotation","reflection","configuration"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}