NationalSecurityAgency/ghidra · error · IllegalArgumentException

Can only directly delete values for maps where the entry is

Error message

Can only directly delete values for maps where the entry is the value

What it means

Thrown by DBTraceAddressSnapRangePropertyMap.deleteValue(T value) when the value passed is not an instance of AbstractDBTraceAddressSnapRangePropertyMapData. The map-level deleteValue method can only delete values that are themselves map entry data objects (where the entry IS the value). For maps where values are separate from entries, you must use deleteData() with the entry instead. This is an IllegalArgumentException (unchecked).

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/DBTraceAddressSnapRangePropertyMap.java:117

			boolean createIfAbsent) {
		return super.getForSpace(space, createIfAbsent);
	}

	@Override
	public Lock readLock() {
		return lock.readLock();
	}

	@Override
	public Lock writeLock() {
		return lock.writeLock();
	}

	@Override
	@SuppressWarnings({ "unchecked" })
	public void deleteValue(T value) {
		if (!(value instanceof AbstractDBTraceAddressSnapRangePropertyMapData)) {
			throw new IllegalArgumentException(
				"Can only directly delete values for maps where the entry is the value");
		}
		deleteData((DR) value);
	}

	// NOTE: DR is not declared in interface
	public void deleteData(DR data) {
		AddressSpace space = data.range.getAddressSpace();
		delegateDeleteV(space, m -> m.deleteData(data));
	}

	@Override
	public T put(TraceAddressSnapRange shape, T value) {
		return delegateWrite(shape.getRange().getAddressSpace(), m -> m.put(shape, value));
	}

	@Override
	public boolean remove(TraceAddressSnapRange shape, T value) {

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Use the remove(TraceAddressSnapRange shape, T value) or remove(Entry) methods instead of deleteValue() for non-entry values.
  2. If using a map where the value IS the entry (e.g., DBTraceStringPropertyMapEntry), ensure you pass the entry data object, not the raw value.
  3. Check value instanceof AbstractDBTraceAddressSnapRangePropertyMapData before calling deleteValue().

Example fix

// before
map.deleteValue(myValue);

// after
// Use remove by shape instead
map.remove(shape, myValue);
// Or if value is the entry:
if (myValue instanceof AbstractDBTraceAddressSnapRangePropertyMapData) {
    map.deleteValue(myValue);
}
Defensive patterns

Strategy: validation

Validate before calling

// Check before calling deleteValue on the map
if (value instanceof AbstractDBTraceAddressSnapRangePropertyMapData) {
    map.deleteValue(value);
} else {
    // use remove(shape, value) or remove(entry) instead
}

Type guard

// Type guard for safe deleteValue calls
static <T> boolean isEntryValue(T value) {
    return value instanceof AbstractDBTraceAddressSnapRangePropertyMapData;
}

Prevention

When it happens

Trigger: Calling deleteValue(someValue) on a DBTraceAddressSnapRangePropertyMap where someValue is a plain domain object (e.g., a String, Integer, or custom value) rather than an AbstractDBTraceAddressSnapRangePropertyMapData instance. This happens when the caller treats the property map like a generic key-value store without understanding the entry-as-value constraint.

Common situations: Using a DBTraceAddressSnapRangePropertyMap with a value type that is not the entry data class. Generic map manipulation code that assumes deleteValue accepts any value type.

Related errors


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