NationalSecurityAgency/ghidra · error · IllegalArgumentException
Memory addresses cannot be associated with a thread
Error message
Memory addresses cannot be associated with a thread
What it means
Thrown by DBTraceSymbolManager.assertValidThreadAddress: a non-null thread may only be paired with a non-memory (i.e. register) address. Memory addresses exist in address spaces that are independent of any thread, so associating one with a thread is a logical error. Register addresses are thread-scoped and are the only addresses that may carry a thread.
Source
Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolManager.java:364
for (AbstractDBTraceSymbolSingleTypeView<?> view : symbolViews.values()) {
view.invalidateCache();
}
if (globalNamespace.isDeleted()) {
throw new AssertionError();
}
}
}
// Internal
public void replaceDataTypes(Map<Long, Long> dataTypeReplacementMap) {
// Would apply to functions and variables, but those are not supported.
}
protected void assertValidThreadAddress(TraceThread thread, Address address) {
if (thread != null && address.isMemoryAddress()) {
throw new IllegalArgumentException(
"Memory addresses cannot be associated with a thread");
}
}
@Override
public Trace getTrace() {
return trace;
}
@Override
public AbstractDBTraceSymbol getSymbolByID(long symbolID) {
if (symbolID == GlobalNamespace.GLOBAL_NAMESPACE_ID) {
return globalNamespace;
}
byte typeID = unpackTypeID(symbolID);
AbstractDBTraceSymbolSingleTypeView<?> view = symbolViews.get(typeID);
if (view == null) {
return null;View on GitHub (pinned to d5f144c24d)
Solutions
- For memory addresses pass thread = null.
- Only pass a non-null thread when the address is a register address (address.isRegisterAddress() / address.isMemoryAddress() == false).
- Split the call site: memory labels go to the no-thread overload, register symbols to the thread-scoped one.
Example fix
// before symMgr.createLabel(span, memAddr, name, ns, SourceType.USER, thread /* non-null */); // after TraceThread t = memAddr.isMemoryAddress() ? null : thread; symMgr.createLabel(span, memAddr, name, ns, SourceType.USER, t);
Defensive patterns
Strategy: validation
Validate before calling
TraceThread t = (thread != null && address.isMemoryAddress()) ? null : thread; symMgr.createLabel(span, address, name, ns, source, t);
Type guard
static boolean threadAddressValid(TraceThread thread, Address address) {
return thread == null || !address.isMemoryAddress();
} Prevention
- Pair a thread only with register (non-memory) addresses; pass null thread for memory addresses.
- Decide thread-scoping by address space at the call site, not unconditionally.
When it happens
Trigger: Creating a symbol (label, variable, etc.) with a thread argument while passing a memory-space Address (address.isMemoryAddress() == true), e.g. a register-space address was expected but a memory address was supplied.
Common situations: Confusing register-context symbols with memory labels; passing a register Address that is actually a memory-mapped register; auto-wiring a thread into every symbol creation call regardless of address space.
Related errors
- Given namespace is not in this trace
- Given symbol is not in this trace
- Code unit would extend beyond address space
- Space does not exist
- Given namespace is not part of this trace
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/a2bb88aea31921f3.
Report an issue: GitHub.