{"record":{"id":"01d11bc4fae596f9","repo":"NationalSecurityAgency/ghidra","slug":"dbannotatedcolumn-fields-must-be-dbobjectcolumn-t","errorCode":null,"errorMessage":"@DBAnnotatedColumn fields must be DBObjectColumn type. Got {}","messagePattern":"@DBAnnotatedColumn fields must be DBObjectColumn type\\. Got (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java","lineNumber":1177,"sourceCode":"\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);\n\t\t\t\ttry {\n\t\t\t\t\tDBObjectColumn already = (DBObjectColumn) f.get(null);\n\t\t\t\t\tif (already == null) {\n\t\t\t\t\t\tf.set(null, DBObjectColumn.get(columnNumber.intValue()));\n\t\t\t\t\t}","sourceCodeStart":1159,"sourceCodeEnd":1195,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java#L1159-L1195","documentation":"The column-handle injection only knows how to write a DBObjectColumn instance into the field (via f.set(None, DBObjectColumn.get(columnNumber))). The annotation's contract is strictly a `static DBObjectColumn` field; the check is an exact-type comparison `f.getType() != DBObjectColumn.class`, so any other declared type - even a subclass of DBObjectColumn, or the value's domain type - is rejected.","triggerScenarios":"A field annotated @DBAnnotatedColumn whose declared type is not exactly DBObjectColumn.class (e.g. `static String NAME`, `static Long NAME`, or `static MyColSubclass NAME`). Hit when writeColumnNumbers runs during store construction.","commonSituations":"Declaring the handle as the value type (String/Long) instead of DBObjectColumn; using a DBObjectColumn subclass; copy-paste where the type was left as the domain type.","solutions":["Change the field's declared type to exactly DBObjectColumn.","Keep the `static` modifier from the prior check.","If you wanted stored data, use @DBAnnotatedField and a supported value type instead."],"exampleFix":"// before\n@DBAnnotatedColumn(\"name\")\nstatic String NAME;\n// after\n@DBAnnotatedColumn(\"name\")\nstatic DBObjectColumn NAME;","handlingStrategy":"validation","validationCode":"for (Field f : objectType.getDeclaredFields()) {\n    if (f.isAnnotationPresent(DBAnnotatedColumn.class) && f.getType() != DBObjectColumn.class) {\n        throw new IllegalStateException(\"@DBAnnotatedColumn field must be DBObjectColumn: \" + f);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always declare column handles as `static DBObjectColumn NAME;`.","Distinguish value fields (@DBAnnotatedField) from column-handle fields (@DBAnnotatedColumn) in a coding-standard note."],"tags":["database","annotation","reflection","types"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}