NationalSecurityAgency/ghidra · error · IllegalArgumentException

Associated symbol and reference must have connected lifespan

Error message

Associated symbol and reference must have connected lifespans

What it means

Thrown as IllegalArgumentException by DBTraceReference.setAssociatedSymbol when the associated symbol implements TraceSymbolWithLifespan and its lifespan does not intersect the reference's lifespan. Both the symbol and the reference exist over a range of snaps; associating them is only valid where they coexist, so an empty intersection is rejected after the address check passes.

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReference.java:157

	}

	@Override
	public void setAssociatedSymbol(Symbol symbol) {
		try (LockHold hold = LockHold.lock(ent.space.lock.writeLock())) {
			AbstractDBTraceSymbol dbSym = getTrace().getSymbolManager().assertIsMine(symbol);
			if (ent.symbolId == symbol.getID()) {
				return;
			}
			Address toAddress = getToAddress();
			if (!Objects.equals(symbol.getAddress(), toAddress)) {
				throw new IllegalArgumentException(String.format(
					"Symbol address (%s) of '%s' must match Reference's to address (%s)",
					symbol.getAddress(), symbol.getName(), toAddress));
			}
			if (symbol instanceof TraceSymbolWithLifespan) {
				TraceSymbolWithLifespan symWl = (TraceSymbolWithLifespan) symbol;
				if (!symWl.getLifespan().intersects(getLifespan())) {
					throw new IllegalArgumentException(
						"Associated symbol and reference must have connected lifespans");
				}
			}
			ent.setSymbolId(symbol.getID());
			getTrace().setChanged(new TraceChangeRecord<>(TraceEvents.SYMBOL_ASSOCIATION_ADDED,
				ent.space.space, dbSym, null, this));
		}
	}

	@Override
	public void clearAssociatedSymbol() {
		try (LockHold hold = LockHold.lock(ent.space.lock.writeLock())) {
			if (ent.symbolId == -1) {
				return;
			}
			TraceSymbol oldSymbol = getTrace().getSymbolManager().getSymbolByID(ent.symbolId);
			ent.setSymbolId(-1);
			getTrace().setChanged(new TraceChangeRecord<>(TraceEvents.SYMBOL_ASSOCIATION_REMOVED,

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Ensure the symbol's lifespan overlaps the reference's: extend the symbol's lifespan to cover the reference's snap range.
  2. Adjust the reference's lifespan to fall within the symbol's lifespan before associating.
  3. Create a separate symbol instance for the relevant snap window.

Example fix

// before
ref.setAssociatedSymbol(sym); // disjoint lifespans
// after
// widen symbol lifespan to intersect reference's
sym.setLifespan(Lifespan.union(sym.getLifespan(), ref.getLifespan()));
ref.setAssociatedSymbol(sym);
Defensive patterns

Strategy: validation

Validate before calling

if (symbol instanceof TraceSymbolWithLifespan) {
    Lifespan symSpan = ((TraceSymbolWithLifespan) symbol).getLifespan();
    if (!symSpan.intersects(ref.getLifespan())) {
        // widen symbol lifespan or skip association
    }
}
ref.setAssociatedSymbol(symbol);

Type guard

static boolean lifespansConnected(TraceSymbolWithLifespan s, Reference r) {
    return s.getLifespan().intersects(r.getLifespan());
}

Prevention

When it happens

Trigger: Associating a symbol whose lifespan is [0,5] with a reference whose lifespan is [6,10]. Setting an association across a snap where the symbol was not yet / no longer defined.

Common situations: Time-travel debugging where symbols and references have different lifespans; importing reference data from a snap outside the symbol's window.

Related errors


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