{"record":{"id":"8a3182b628974489","repo":"NationalSecurityAgency/ghidra","slug":"code-units-cannot-overlap","errorCode":null,"errorMessage":"Code units cannot overlap","messagePattern":"Code units cannot overlap","errorType":"exception","errorClass":"CodeUnitInsertionException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractBaseDBTraceDefinedUnitsView.java","lineNumber":404,"sourceCode":"\t\tif (extending == null) {\n\t\t\ttoScan = span;\n\t\t}\n\t\telse if (span.lmax() <= extending.getEndSnap()) {\n\t\t\t// we're shrinking or staying the same, so not possible to collide with others\n\t\t\treturn span;\n\t\t}\n\t\telse {\n\t\t\ttoScan = span.withMin(extending.getEndSnap() + 1);\n\t\t}\n\t\tT truncateBy =\n\t\t\tmapSpace.reduce(TraceAddressSnapRangeQuery.intersecting(range, toScan)\n\t\t\t\t\t.starting(Rectangle2DDirection.BOTTOMMOST))\n\t\t\t\t\t.firstValue();\n\t\tif (truncateBy == null) {\n\t\t\treturn span;\n\t\t}\n\t\tif (truncateBy.getStartSnap() <= span.lmin()) {\n\t\t\tthrow new CodeUnitInsertionException(\"Code units cannot overlap\");\n\t\t}\n\t\treturn span.withMax(truncateBy.getStartSnap() - 1);\n\t}\n\n\tprotected long computeTruncatedMax(Lifespan lifespan, T extending, AddressRange range)\n\t\t\tthrows CodeUnitInsertionException {\n\t\t// First, truncate lifespan to the next code unit when upper bound is max\n\t\tif (!lifespan.maxIsFinite()) {\n\t\t\tlifespan = space.instructions.truncateSoonestDefined(lifespan, extending, range);\n\t\t\tlifespan = space.definedData.truncateSoonestDefined(lifespan, extending, range);\n\t\t}\n\t\t// Second, truncate lifespan to the next change of bytes in the range\n\t\tDBTraceMemorySpace memSpace =\n\t\t\tspace.trace.getMemoryManager().getMemorySpace(space.space, true);\n\t\tLifespan fullSpan = extending == null ? lifespan : lifespan.bound(extending.getLifespan());\n\t\tlong endSnap = memSpace.getFirstChange(fullSpan, range);\n\t\tif (endSnap == Long.MIN_VALUE) {\n\t\t\treturn lifespan.lmax();","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/AbstractBaseDBTraceDefinedUnitsView.java#L386-L422","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nview.create(Lifespan.span(0, 100), address, platform, dataType);\n// fails if a unit exists at snap 50 at the same address\n\n// after — clear the conflicting range first\nDefinedData existing = view.getContaining(50, address);\nif (existing != null) {\n    existing.delete(); // or existing.setLifespan(...) to shrink\n}\nview.create(Lifespan.span(0, 100), address, platform, dataType);","handlingStrategy":"try-catch","validationCode":"// Before defining a unit, check for overlapping defined units\nLifespan span = Lifespan.span(startSnap, endSnap);\nAddressRange range = new AddressRangeImpl(address, address.add(length - 1));\nCollection<? extends CodeUnit> conflicts =\n    space.definedUnits.getIntersecting(new ImmutableTraceAddressSnapRange(range, span));\nif (!conflicts.isEmpty()) {\n    // delete or shrink conflicting units first\n    for (CodeUnit cu : conflicts) {\n        // handle conflict\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    view.create(lifespan, address, platform, dataType);\n} catch (CodeUnitInsertionException e) {\n    if (e.getMessage().equals(\"Code units cannot overlap\")) {\n        // Identify and clear the conflicting unit, then retry\n        CodeUnit existing = view.getContaining(lifespan.lmin(), address);\n        if (existing != null) {\n            existing.delete();\n            view.create(lifespan, address, platform, dataType);\n        }\n    } else {\n        throw e;\n    }\n}","preventionTips":["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."],"tags":["code-unit","overlap","lifespan","trace-modeling"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}