NationalSecurityAgency/ghidra · error · IllegalArgumentException
Unsupported value class: {}
Error message
Unsupported value class: {} What it means
Thrown by DBTraceAddressPropertyManager.doCreateMap when the requested property value class is none of the supported types. Supported classes are exactly Integer, Long, String, Void, or any subclass of ghidra.framework.save.Saveable. Any other Class<T> (e.g. Double, Boolean, Address, a plain POJO) reaches the terminal throw. This is a programming contract violation rather than a runtime data problem.
Source
Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/property/DBTraceAddressPropertyManager.java:167
}
if (valueClass == Void.class) {
return (AbstractDBTracePropertyMap<T, ?>) new DBTraceVoidPropertyMap(tableName, dbh,
openMode, lock, TaskMonitor.DUMMY, baseLanguage, trace, threadManager);
}
if (Saveable.class.isAssignableFrom(valueClass)) {
Class<? extends Saveable> saveableClass = valueClass.asSubclass(Saveable.class);
return (AbstractDBTracePropertyMap<T, ?>) new DBTraceSaveablePropertyMap<>(
tableName, dbh, openMode, lock, TaskMonitor.DUMMY, baseLanguage, trace,
threadManager, saveableClass);
}
}
catch (IOException e) {
dbError(e);
}
catch (VersionException e) {
throw new AssertionError(e);
}
throw new IllegalArgumentException("Unsupported value class: " + valueClass);
}
@Override
public <T> AbstractDBTracePropertyMap<T, ?> createPropertyMap(String name, Class<T> valueClass)
throws DuplicateNameException {
try (LockHold hold = LockHold.lock(lock.writeLock())) {
if (propertyMapsByName.containsKey(name)) {
throw new DuplicateNameException(name);
}
DBTraceAddressPropertyEntry ent = propertyStore.create();
ent.set(name, valueClass);
AbstractDBTracePropertyMap<T, ?> map = doCreateMap(name, OpenMode.CREATE, valueClass);
ent.map = map;
propertyMapsByName.put(name, map);
return map;
}
}
View on GitHub (pinned to d5f144c24d)
Solutions
- Use one of the built-in classes: Integer, Long, String, or Void.
- For complex types, implement a class extending ghidra.framework.save.Saveable and pass its Class.
- If you need a boolean, store it as a Void presence marker or wrap in a Saveable.
Example fix
// before
propMgr.createPropertyMap("flag", Boolean.class);
// after
propMgr.createPropertyMap("flag", Integer.class); // store 0/1
// or implement BooleanSaveable extends Saveable Defensive patterns
Strategy: type-guard
Validate before calling
boolean supported = valueClass == Integer.class || valueClass == Long.class ||
valueClass == String.class || valueClass == Void.class ||
Saveable.class.isAssignableFrom(valueClass);
if (!supported) throw new IllegalArgumentException("unsupported");
mgr.createPropertyMap(name, valueClass); Type guard
static boolean isSupportedValueClass(Class<?> c) {
return c == Integer.class || c == Long.class || c == String.class
|| c == Void.class || Saveable.class.isAssignableFrom(c);
} Prevention
- Restrict property value types to Integer, Long, String, Void, or a Saveable subclass.
- Wrap non-conforming types in a custom Saveable.
When it happens
Trigger: Calling createPropertyMap(name, Double.class), createPropertyMap(name, Address.class), or getOrCreatePropertyMap with an arbitrary custom class that is not a Saveable subclass.
Common situations: Developer assumes arbitrary value types are allowed and passes Boolean/Double/byte[]. Passing a Saveable subclass that fails the isAssignableFrom check due to a raw/generic Class token erasure.
Related errors
- Invalid number of elements specified: {}
- pos cannot be less than zero
- %s: unknown demangling style `%s'
- Max ascii string size is %d you provided: %lu chars. Exiting
- need even-number of ascii chars for byte-stream: (offset: %0
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/b1c9f79090501a32.
Report an issue: GitHub.