NationalSecurityAgency/ghidra · error · CodeUnitInsertionException

Length override of {newLength} conflicts with code unit at {

Error message

Length override of {newLength} conflicts with code unit at {cu.getMinAddress}, lifespan={cu.getLifespan}

What it means

Thrown by DBTraceInstruction when setting a length override that would cause the instruction's expanded range to collide with an adjacent defined code unit. When the new length (newLength) exceeds the current unit length, the method checks the extended range [minAddr.next(), newEndAddr] for any other defined unit at the same lifespan. If one is found, the override is rejected because it would overlap that unit. This prevents silent corruption of the code listing from length overrides.

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceInstruction.java:596

	public void setLengthOverride(int length) throws CodeUnitInsertionException {
		int oldLengthOverride = this.lengthOverride;
		try (LockHold hold = space.trace.lockWrite()) {
			checkDeleted();
			InstructionPrototype proto = getPrototype();
			length = InstructionDB.checkLengthOverride(length, proto);
			if (length == lengthOverride) {
				return; // no change
			}

			int newLength = length != 0 ? length : proto.getLength();
			if (newLength > getLength()) {
				Address minAddr = getMinAddress();
				Address newEndAddr = minAddr.add(newLength - 1);
				TraceAddressSnapRange tasr = new ImmutableTraceAddressSnapRange(
					new AddressRangeImpl(minAddr.next(), newEndAddr), getLifespan());
				for (AbstractDBTraceCodeUnit<?> cu : space.definedUnits.getIntersecting(tasr)) {
					if (cu != this) {
						throw new CodeUnitInsertionException(
							"Length override of " + newLength + " conflicts with code unit at " +
								cu.getMinAddress() + ", lifespan=" + cu.getLifespan());
					}
				}
			}

			updateLengthOverride(length);
		}
		space.trace.setChanged(new TraceChangeRecord<>(
			TraceEvents.INSTRUCTION_LENGTH_OVERRIDE_CHANGED, space.space, this, oldLengthOverride,
			length));
	}

	private void updateLengthOverride(int length) {
		flags &= LENGTH_OVERRIDE_CLEAR_MASK;
		flags |= (length << LENGTH_OVERRIDE_SHIFT);
		lengthOverride = length;
		update(FLAGS_COLUMN);

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Delete the conflicting adjacent code unit before setting the override: clear the range [addr+1, addr+newLength-1].
  2. Set a smaller length override that does not collide with the neighbor.
  3. Clear and re-disassemble the region first, then apply the override.
  4. Shrink the conflicting unit's lifespan so it no longer overlaps.

Example fix

// before
instruction.setLengthOverride(8); // adjacent unit at addr+4 blocks

// after — clear the conflicting range first
CodeUnit neighbor = space.definedUnits.getAt(snap, instruction.getMinAddress().add(4));
if (neighbor != null) {
    neighbor.delete();
}
instruction.setLengthOverride(8);
Defensive patterns

Strategy: validation

Validate before calling

// Before setting a length override, check for adjacent conflicts
int newLength = desiredLength;
if (newLength > instruction.getLength()) {
    Address minAddr = instruction.getMinAddress();
    Address newEndAddr = minAddr.add(newLength - 1);
    TraceAddressSnapRange tasr = new ImmutableTraceAddressSnapRange(
        new AddressRangeImpl(minAddr.next(), newEndAddr), instruction.getLifespan());
    for (CodeUnit cu : space.definedUnits.getIntersecting(tasr)) {
        if (cu != instruction) {
            // Conflict — clear it first
            cu.delete();
        }
    }
}
instruction.setLengthOverride(newLength);

Try / catch

try {
    instruction.setLengthOverride(newLength);
} catch (CodeUnitInsertionException e) {
    if (e.getMessage().startsWith("Length override") && e.getMessage().contains("conflicts")) {
        // Clear the conflicting adjacent unit and retry
        Address minAddr = instruction.getMinAddress();
        for (CodeUnit cu : space.definedUnits.getIntersecting(
                new ImmutableTraceAddressSnapRange(
                    new AddressRangeImpl(minAddr.next(), minAddr.add(newLength - 1)),
                    instruction.getLifespan()))) {
            if (cu != instruction) cu.delete();
        }
        instruction.setLengthOverride(newLength);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling instruction.setLengthOverride(newLength) (or equivalent) where newLength > current length and another instruction or data unit occupies the bytes the instruction would grow into, within the same lifespan. The method iterates space.definedUnits.getIntersecting(tasr) and throws on the first foreign unit.

Common situations: Overriding instruction length to disassemble a longer encoding when the adjacent bytes already have a defined unit; conflict between user overrides and auto-disassembly results; stale code units from a previous disassembly pass blocking the override.

Related errors


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