NationalSecurityAgency/ghidra · error · IllegalArgumentException
No variant codec for class {}
Error message
No variant codec for class {} What it means
Thrown (unchecked IllegalArgumentException) by PrimitiveCodec.getCodec(Class) when the given class has no registered variant codec. Variant fields (Object-typed) support a fixed set of primitive/Array/String/Address/RecRange types registered in CODECS_BY_CLASS (BOOL, BYTE, CHAR, SHORT, INT, LONG, STRING, the matching arrays, ADDRESS, RANGE — notably no float/double). Any other class is unsupported.
Source
Thrown at Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBCachedObjectStoreFactory.java:1016
SHORT_ARR, INT_ARR, LONG_ARR, STRING_ARR, ADDRESS, RANGE)
.collect(Collectors.toMap(c -> c.getSelector(), c -> c));
Map<Class<?>, PrimitiveCodec<?>> CODECS_BY_CLASS = CODECS_BY_SELECTOR.values()
.stream()
.collect(Collectors.toMap(c -> c.getValueClass(), c -> c));
/**
* Get the codec for the given type
*
* @param <T> the type
* @param cls the class describing {@link T}
* @return the codec
* @throws IllegalArgumentException if the type is not supported
*/
static <T> PrimitiveCodec<T> getCodec(Class<T> cls) {
@SuppressWarnings("unchecked")
PrimitiveCodec<T> obj = (PrimitiveCodec<T>) CODECS_BY_CLASS.get(cls);
if (obj == null) {
throw new IllegalArgumentException("No variant codec for class " + cls);
}
return obj;
}
/**
* Get the codec for the given selector
*
* @param sel the selector
* @return the codec
* @throws IllegalArgumentException if the selector is unknown
*/
static PrimitiveCodec<?> getCodec(byte sel) {
PrimitiveCodec<?> obj = CODECS_BY_SELECTOR.get(sel);
if (obj == null) {
throw new IllegalArgumentException("No variant codec with selector " + sel);
}
return obj;
}View on GitHub (pinned to d5f144c24d)
Solutions
- Store only a supported variant type (boolean/byte/char/short/int/long, String, the matching arrays, Address, or RecRange). Convert other types before storage.
- For float/double (deliberately unsupported), encode as a long via Float.floatToIntBits / Double.doubleToLongBits and store the long, or use a dedicated typed field.
- For custom objects, serialize to a String or byte[] and store that, or define a proper annotated sub-store.
Example fix
// before variantField.set(myObject.getScore()); // Float -> "No variant codec for class java.lang.Float" // after: encode unsupported numeric types to a supported one variantField.set(Float.floatToIntBits(myObject.getScore())); // stored as Integer
Defensive patterns
Strategy: validation
Validate before calling
// Only store supported variant types
Set<Class<?>> supported = Set.of(boolean.class, byte.class, char.class, short.class,
int.class, long.class, String.class, Address.class, RecRange.class /* + matching arrays */);
if (!supported.contains(value.getClass())) {
// convert (e.g. float -> int bits, custom -> String/byte[]) before storing
} Prevention
- Store only supported primitive/String/Array/Address/RecRange types in variant fields.
- Encode float/double as int/long bits (they are deliberately unsupported).
- Serialize custom objects to String or byte[] rather than storing them directly.
When it happens
Trigger: Storing a value whose class isn't in the supported variant set into a variant (Object-typed) DB field — e.g. a Float/Double (explicitly unsupported, per the 'No floats?' comment), a custom object, or a BigInteger. getCodec is called to pick the encoder and finds none.
Common situations: Putting a float/double into a variant field; storing a custom/domain class instead of a primitive; storing a Long where the registry only has the primitive-backed wrapper; assuming arbitrary Object types are supported.
Related errors
- No variant codec with selector {}
- Column {} is not of type {}! It is {}
- Given field does not apply to given object type
- Given field does not have the given type: {} != {}
- Too many constants in {} to encode as a byte
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/dd4bb83555d8d225.
Report an issue: GitHub.