{"record":{"id":"755771437f42d424","repo":"NationalSecurityAgency/ghidra","slug":"no-variant-codec-with-selector","errorCode":null,"errorMessage":"No variant codec with selector {}","messagePattern":"No variant codec with selector (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java","lineNumber":1031,"sourceCode":"\t\t\t@SuppressWarnings(\"unchecked\")\n\t\t\tPrimitiveCodec<T> obj = (PrimitiveCodec<T>) CODECS_BY_CLASS.get(cls);\n\t\t\tif (obj == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"No variant codec for class \" + cls);\n\t\t\t}\n\t\t\treturn obj;\n\t\t}\n\n\t\t/**\n\t\t * Get the codec for the given selector\n\t\t * \n\t\t * @param sel the selector\n\t\t * @return the codec\n\t\t * @throws IllegalArgumentException if the selector is unknown\n\t\t */\n\t\tstatic PrimitiveCodec<?> getCodec(byte sel) {\n\t\t\tPrimitiveCodec<?> obj = CODECS_BY_SELECTOR.get(sel);\n\t\t\tif (obj == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"No variant codec with selector \" + sel);\n\t\t\t}\n\t\t\treturn obj;\n\t\t}\n\t}\n\n\t/**\n\t * A custom codec for field of \"variant\" type\n\t * \n\t * <p>\n\t * This is suitable for use on fields of type {@link Object}; however, only certain types can\n\t * actually be encoded. The encoding uses a 1-byte type selector followed by the byte-array\n\t * encoded value.\n\t */\n\tpublic static class VariantDBFieldCodec<OT extends DBAnnotatedObject>\n\t\t\textends AbstractDBFieldCodec<Object, OT, BinaryField> {\n\t\tpublic VariantDBFieldCodec(Class<OT> objectType, Field field, int column) {\n\t\t\tsuper(Object.class, objectType, BinaryField.class, field, column);\n\t\t}","sourceCodeStart":1013,"sourceCodeEnd":1049,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java#L1013-L1049","documentation":"Thrown (unchecked IllegalArgumentException) by PrimitiveCodec.getCodec(byte sel) when reading a variant field whose stored 1-byte type selector does not map to any known codec in CODECS_BY_SELECTOR. Each variant value is prefixed by a selector byte identifying its codec; an unknown selector means the data was written by a newer/different code version, the registry changed, or the bytes are corrupt.","triggerScenarios":"Reading variant-field data that was encoded with a selector byte this code version doesn't recognise — typically a forward-compatibility/version-skew (data written by newer code with an added codec type) or byte-level corruption of the stored record.","commonSituations":"Opening a database created by a newer Ghidra/version that added a variant codec; a registry edit that removed or renumbered a selector; storage corruption producing a garbage selector byte; partial/aborted writes leaving a bad header.","solutions":["Upgrade the reading code to a version whose codec registry includes the stored selector (align writer and reader versions).","If the registry was intentionally changed, re-encode/migrate the affected records so their selectors are current.","For corruption, restore from backup or rebuild the affected store from source data.","Add a defensive check: log the unknown selector and skip/quarantine the record rather than aborting the whole read."],"exampleFix":"// before: reading a newer-format variant field throws\nObject v = store.getVariantField(rec); // \"No variant codec with selector 17\"\n\n// after: tolerate unknown selectors from version skew\nbyte sel = rec.readSelector();\nif (!PrimitiveCodec.hasCodec(sel)) {\n    log.warn(\"unknown variant selector {}; skipping record\", sel);\n    continue;\n}\nObject v = PrimitiveCodec.getCodec(sel).decode(rec);","handlingStrategy":"try-catch","validationCode":"// Check the selector is known before decoding\nif (!PrimitiveCodec.CODECS_BY_SELECTOR.containsKey(sel)) {\n    // version skew or corruption: upgrade reader, migrate data, or skip record\n}","typeGuard":null,"tryCatchPattern":"try {\n    Object v = PrimitiveCodec.getCodec(sel).decode(buf);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"No variant codec with selector\")) { /* log + skip/quarantine */ }\n    else throw e;\n}","preventionTips":["Keep writer and reader codec registries version-aligned.","Migrate/re-encode records when the selector set changes.","Add a defensive unknown-selector check that logs and skips rather than aborting the read."],"tags":["database","codec","variant-field","version-mismatch","corruption","illegal-argument","unchecked-exception"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}