NationalSecurityAgency/ghidra · error · ClassCastException

Cannot convert

Error message

Cannot convert 

What it means

Thrown by DBTraceObjectRegister.getValue() when the stored register value is neither a byte[] nor a String, and thus cannot be converted to a byte array. The method checks for byte[] (returned directly) and String (parsed as hex via BigInteger). Any other type triggers a ClassCastException (unchecked) with the message 'Cannot convert {val} to byte array for register value'.

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/memory/DBTraceObjectRegister.java:89

	}

	@Override
	public byte[] getValue(long snap) {
		TraceObjectValue ov = object.getValue(snap, TraceRegister.KEY_VALUE);
		if (ov == null) {
			return null;
		}
		Object val = ov.getValue();
		if (val instanceof byte[] arr) {
			// TODO: Should I correct mismatched size?
			return arr;
		}
		if (val instanceof String str) {
			// Always base 16. Model API says byte array for register value is big endian.
			BigInteger bigVal = new BigInteger(str, 16);
			return Utils.bigIntegerToBytes(bigVal, getByteLength(snap), true);
		}
		throw new ClassCastException("Cannot convert " + val + " to byte array for register value");
	}

	@Override
	public void setState(Lifespan lifespan, TraceMemoryState state) {
		// NB. There's no model equivalent, so encode using ordinal
		object.setValue(lifespan, KEY_STATE, state.ordinal());
	}

	@Override
	public TraceMemoryState getState(long snap) {
		return TraceMemoryState.values()[TraceObjectInterfaceUtils.getValue(object, snap, KEY_STATE,
			Integer.class, TraceMemoryState.UNKNOWN.ordinal())];
	}

	@Override
	public TraceChangeRecord<?, ?> translateEvent(TraceChangeRecord<?, ?> rec) {
		// TODO: Once we decide how to map registers....
		return null;

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Ensure register values are always stored as byte[] or hex String via setValue() — never as other types.
  2. If reading a potentially incompatible value, use the object model directly: object.getValue(snap, KEY_VALUE) and handle the Object type manually.
  3. Convert numeric register values to properly-sized byte arrays before storing them on the register object.

Example fix

// before: storing wrong type
reg.getObject().setValue(lifespan, TraceRegister.KEY_VALUE, 42);

// after: store as byte[] or hex string
int len = reg.getByteLength(snap);
reg.setValue(lifespan,
    Utils.bigIntegerToBytes(BigInteger.valueOf(42), len, true));
Defensive patterns

Strategy: validation

Validate before calling

// Check the stored value type before reading
TraceObjectValue ov = reg.getObject().getValue(snap, TraceRegister.KEY_VALUE);
if (ov != null) {
    Object val = ov.getValue();
    if (!(val instanceof byte[]) && !(val instanceof String)) {
        // incompatible type; convert or re-store
        // store as byte[] to fix
        reg.setValue(Lifespan.at(snap), convertToBytes(val, reg.getByteLength(snap)));
    }
}

Type guard

// Type guard for safe register value retrieval
static boolean isConvertibleRegisterValue(Object val) {
    return val instanceof byte[] || val instanceof String;
}

Prevention

When it happens

Trigger: Calling getValue(snap) on a DBTraceObjectRegister where the underlying TraceObjectValue for KEY_VALUE holds a type other than byte[] or String — for example, an Integer, Long, Boolean, or a custom object. This happens when the register's value key was set via the generic object model API with an incompatible value type.

Common situations: Interoperability issues when the same object key is written by different subsystems (one writes byte[], another writes a numeric type). Trace objects that were populated by a target connector that stored register values as integers rather than byte arrays. Schema evolution where the value type convention changed.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/b58a6942c8f15023. Report an issue: GitHub.