NationalSecurityAgency/ghidra · error · IllegalArgumentException

Cannot create or remove DEFAULT symbols

Error message

Cannot create or remove DEFAULT symbols

What it means

Thrown as IllegalArgumentException by validateNameAndSource when the source type transitions to or from SourceType.DEFAULT (exclusive-or of the two states). DEFAULT is a reserved source state that symbols are created with implicitly and cannot be explicitly assigned or removed via setName. You may only move between non-DEFAULT sources (ANALYSIS, IMPORTED, USER_DEFINED), or have the framework manage DEFAULT transitions internally.

Source

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

	@Override
	public boolean isValidParent(Namespace ns) {
		DBTraceNamespaceSymbol dbns = manager.checkIsMine(ns);
		if (dbns == null) {
			return false;
		}
		return MySymbolTypes.VALUES.get(this.getSymbolType().getID()).isValidParent(dbns);
	}

	protected DBTraceNamespaceSymbol checkCircular(DBTraceNamespaceSymbol newParent)
			throws CircularDependencyException {
		return newParent;
	}

	protected Pair<String, SourceType> validateNameAndSource(String newName, SourceType newSource)
			throws InvalidInputException {
		if ((newSource == SourceType.DEFAULT) ^ (getSource() == SourceType.DEFAULT)) {
			throw new IllegalArgumentException("Cannot create or remove DEFAULT symbols");
		}
		DBTraceSymbolManager.assertValidName(newName);
		return new ImmutablePair<>(newName, newSource);
	}

	@Override
	public void setName(String newName, SourceType newSource)
			throws DuplicateNameException, InvalidInputException {
		assertNotGlobal();
		Pair<String, SourceType> validated = validateNameAndSource(newName, newSource);
		newName = validated.getLeft();
		newSource = validated.getRight();
		try (LockHold hold = LockHold.lock(manager.lock.writeLock())) {
			TraceChangeRecord<?, ?> nameEvent = doSetNameWithEvent(newName);
			TraceChangeRecord<?, ?> sourceEvent = doSetSourceWithEvent(newSource);
			if (nameEvent != null || sourceEvent != null) {
				update(NAME_COLUMN, FLAGS_COLUMN);
			}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Use a non-DEFAULT SourceType (USER_DEFINED / IMPORTED / ANALYSIS) when renaming.
  2. If a symbol is DEFAULT and must stay DEFAULT, do not call setName at all.
  3. To remove a symbol, call remove() rather than downgrading source.

Example fix

// before
sym.setName("new", SourceType.DEFAULT);
// after
sym.setName("new", SourceType.USER_DEFINED);
Defensive patterns

Strategy: validation

Validate before calling

if ((source == SourceType.DEFAULT) ^ (sym.getSource() == SourceType.DEFAULT)) {
    // illegal transition; pick a non-DEFAULT source
    source = SourceType.USER_DEFINED;
}
sym.setName(name, source);

Type guard

static boolean isLegalSourceTransition(SymbolType cur, SourceType next) {
    return !((next == SourceType.DEFAULT) ^ (cur == SourceType.DEFAULT));
}

Prevention

When it happens

Trigger: Calling setName(name, SourceType.DEFAULT) on a non-default symbol, or calling setName(name, USER_DEFINED) on a DEFAULT symbol expecting it to stay DEFAULT. The xor fires when exactly one side is DEFAULT.

Common situations: Scripts that blindly set USER_DEFINED on auto-generated DEFAULT symbols and then try to revert to DEFAULT; tooling unaware of the DEFAULT convention.

Related errors


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