NationalSecurityAgency/ghidra · error · CodeUnitInsertionException
Code units cannot overlap
Error message
Code units cannot overlap
What it means
Thrown by truncateSoonestDefined in AbstractBaseDBTraceDefinedUnitsView when computing the truncation bound for a code unit's lifespan and an existing code unit's start snap is at or before the requested span's minimum. This means a defined code unit already occupies the time range being requested, so the new/modified unit cannot be placed without overlapping it. The truncation logic is meant to shrink the lifespan to just before the next unit, but if the next unit starts at or before the span's beginning, there is no room to truncate into.
Source
Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractBaseDBTraceDefinedUnitsView.java:404
if (extending == null) {
toScan = span;
}
else if (span.lmax() <= extending.getEndSnap()) {
// we're shrinking or staying the same, so not possible to collide with others
return span;
}
else {
toScan = span.withMin(extending.getEndSnap() + 1);
}
T truncateBy =
mapSpace.reduce(TraceAddressSnapRangeQuery.intersecting(range, toScan)
.starting(Rectangle2DDirection.BOTTOMMOST))
.firstValue();
if (truncateBy == null) {
return span;
}
if (truncateBy.getStartSnap() <= span.lmin()) {
throw new CodeUnitInsertionException("Code units cannot overlap");
}
return span.withMax(truncateBy.getStartSnap() - 1);
}
protected long computeTruncatedMax(Lifespan lifespan, T extending, AddressRange range)
throws CodeUnitInsertionException {
// First, truncate lifespan to the next code unit when upper bound is max
if (!lifespan.maxIsFinite()) {
lifespan = space.instructions.truncateSoonestDefined(lifespan, extending, range);
lifespan = space.definedData.truncateSoonestDefined(lifespan, extending, range);
}
// Second, truncate lifespan to the next change of bytes in the range
DBTraceMemorySpace memSpace =
space.trace.getMemoryManager().getMemorySpace(space.space, true);
Lifespan fullSpan = extending == null ? lifespan : lifespan.bound(extending.getLifespan());
long endSnap = memSpace.getFirstChange(fullSpan, range);
if (endSnap == Long.MIN_VALUE) {
return lifespan.lmax();View on GitHub (pinned to d5f144c24d)
Solutions
- Delete or shorten the existing conflicting code unit before inserting the new one: call codeUnit.getLifespan() and delete it for the overlapping snaps.
- Narrow the requested lifespan so its start snap is before the conflicting unit's start snap (the method will truncate to fit).
- Use a different address range or snapshot range that does not collide with existing defined units.
Example fix
// before
view.create(Lifespan.span(0, 100), address, platform, dataType);
// fails if a unit exists at snap 50 at the same address
// after — clear the conflicting range first
DefinedData existing = view.getContaining(50, address);
if (existing != null) {
existing.delete(); // or existing.setLifespan(...) to shrink
}
view.create(Lifespan.span(0, 100), address, platform, dataType); Defensive patterns
Strategy: try-catch
Validate before calling
// Before defining a unit, check for overlapping defined units
Lifespan span = Lifespan.span(startSnap, endSnap);
AddressRange range = new AddressRangeImpl(address, address.add(length - 1));
Collection<? extends CodeUnit> conflicts =
space.definedUnits.getIntersecting(new ImmutableTraceAddressSnapRange(range, span));
if (!conflicts.isEmpty()) {
// delete or shrink conflicting units first
for (CodeUnit cu : conflicts) {
// handle conflict
}
} Try / catch
try {
view.create(lifespan, address, platform, dataType);
} catch (CodeUnitInsertionException e) {
if (e.getMessage().equals("Code units cannot overlap")) {
// Identify and clear the conflicting unit, then retry
CodeUnit existing = view.getContaining(lifespan.lmin(), address);
if (existing != null) {
existing.delete();
view.create(lifespan, address, platform, dataType);
}
} else {
throw e;
}
} Prevention
- Always check for existing code units at the target address+snap before creating new ones.
- Clear conflicting ranges before bulk-annotating instructions or data.
- Coordinate disassembly and data-annotation passes to avoid simultaneous creation at overlapping ranges.
When it happens
Trigger: Calling computeTruncatedMax or the internal truncateSoonestDefined path when an existing instruction or defined-data unit already exists at or before the earliest snap of the requested lifespan at the given address range. This occurs during create() or setEndSnap()/length override operations that invoke truncation.
Common situations: Attempting to define a code unit over a snapshot range that already contains a different code unit at the same addresses; overlapping lifespan ranges when annotating instructions/data across traces; race conditions where two operations define units at overlapping snaps without coordination.
Related errors
- Code units cannot overlap
- Length override of {newLength} conflicts with code unit at {
- Set end-snap of root unit
- Couldn't get requested bytes for CodeUnit
- endpoint cannot be -1
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/8a3182b628974489.
Report an issue: GitHub.