NationalSecurityAgency/ghidra · error · IllegalArgumentException

The given symbol is not part of this trace

Error message

The given symbol is not part of this trace

What it means

Thrown as IllegalArgumentException by removeSymbolSpecial when the symbol looked up by ID from the trace's symbol manager is not identity-equal (==) to the passed symbol. This means the passed Symbol object does not originate from this trace — it belongs to another program/trace, so removing it via this view is invalid.

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewSymbolTable.java:104

	public Symbol createLabel(Address addr, String name, SourceType source)
			throws InvalidInputException {
		return symbolManager.labels().create(program.snap, addr, name, global, source);
	}

	@Override
	public Symbol createLabel(Address addr, String name, Namespace namespace, SourceType source)
			throws InvalidInputException {
		return symbolManager.labels()
				.create(program.snap, addr, name, assertTraceNamespace(namespace), source);
	}

	@Override
	public boolean removeSymbolSpecial(Symbol sym) {
		// TODO: I'm not sure I understand the point of this method...
		try (LockHold hold = program.trace.lockWrite()) {
			AbstractDBTraceSymbol dbSym = symbolManager.getSymbolByID(sym.getID());
			if (sym != dbSym) {
				throw new IllegalArgumentException("The given symbol is not part of this trace");
			}
			if (dbSym.getSymbolType() != SymbolType.FUNCTION) {
				return dbSym.delete();
			}
			Address address = dbSym.getAddress();
			Collection<? extends TraceLabelSymbol> at =
				symbolManager.labels().getAt(program.snap, address, false);
			String name;
			TraceNamespaceSymbol parent;
			SourceType source;
			if (at.isEmpty()) {
				if (dbSym.getSource() == SourceType.DEFAULT) {
					return false; // Can't remove default function symbol
				}
				name = SymbolUtilities.getDefaultFunctionName(address);
				parent = global;
				source = SourceType.DEFAULT;
			}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Only pass symbols obtained from the same trace view's symbol table to removeSymbolSpecial.
  2. Verify sym instanceof TraceSymbol and that sym.getProgram() / getID() resolves to this trace before calling.
  3. Re-resolve the symbol by ID from the current trace's symbol manager before removing.

Example fix

// before
symbolTable.removeSymbolSpecial(sym);

// after
if (sym instanceof TraceSymbol && sym.getID() != -1) {
    AbstractDBTraceSymbol dbSym = trace.getSymbolManager().getSymbolByID(sym.getID());
    if (sym == dbSym) {
        symbolTable.removeSymbolSpecial(sym);
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Re-resolve the symbol by ID from the current trace before removing
if (sym instanceof TraceSymbol) {
    AbstractDBTraceSymbol dbSym =
        trace.getSymbolManager().getSymbolByID(sym.getID());
    if (sym == dbSym) {
        symbolTable.removeSymbolSpecial(sym);
    }
}

Type guard

static boolean isTraceSymbolOf(Symbol s, Trace trace) {
    if (!(s instanceof TraceSymbol)) return false;
    return trace.getSymbolManager().getSymbolByID(s.getID()) == s;
}

Prevention

When it happens

Trigger: Calling removeSymbolSpecial(sym) where sym was obtained from a different Program or trace than the current view, or is a stale/different symbol object with the same ID but different identity.

Common situations: Passing a static-program Symbol to the trace view's symbol table. Reusing symbol handles across multiple open traces. Operating on symbols after switching the active trace.

Related errors


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