NationalSecurityAgency/ghidra · error · IllegalArgumentException

Cannot emulate a trace unless it's opened in the tool.

Error message

Cannot emulate a trace unless it's opened in the tool.

What it means

DebuggerEmulationServicePlugin.requireOpen(trace) checks that the given Trace is in traceManager.getOpenTraces(). Emulation needs the trace to be open in the tool so the platform, mapping, and memory managers are wired up. Passing a trace that was never opened (or was closed) is rejected with IllegalArgumentException.

Source

Thrown at Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java:898

	protected void createRegisterSpaces(Trace trace, TraceSchedule time, TaskMonitor monitor) {
		if (trace.getObjectManager().getRootObject() == null) {
			return;
		}
		// Cause object-register support to copy values into new register spaces
		// TODO: I wish this were not necessary
		monitor.setMessage("Creating register spaces");
		try (Transaction tx = trace.openTransaction("Prepare emulation")) {
			for (TraceThread thread : time.getThreads(trace)) {
				trace.getMemoryManager().getMemoryRegisterSpace(thread, 0, true);
			}
		}
		trace.clearUndo();
	}

	protected void requireOpen(Trace trace) {
		if (!traceManager.getOpenTraces().contains(trace)) {
			throw new IllegalArgumentException(
				"Cannot emulate a trace unless it's opened in the tool.");
		}
	}

	class TraceMappingWaiter extends CompletableFuture<Void>
			implements DebuggerStaticMappingChangeListener {
		private final Trace trace;

		public TraceMappingWaiter(Trace trace) {
			this.trace = trace;
		}

		@Override
		public void mappingsChanged(Set<Trace> affectedTraces, Set<Program> affectedPrograms) {
			if (affectedTraces.contains(trace)) {
				complete(null);
			}
		}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Open the trace in the tool via DebuggerTraceManagerService.openTrace(trace) before requesting emulation.
  2. Guard the call by checking traceManager.getOpenTraces().contains(trace).
  3. Re-open the trace if it was closed, then retry emulation.

Example fix

// before
emuService.startEmulation(trace, snap, monitor); // throws if not opened

// after
if (!traceManager.getOpenTraces().contains(trace)) {
    traceManager.openTrace(trace);
}
emuService.startEmulation(trace, snap, monitor);
Defensive patterns

Strategy: validation

Validate before calling

// Run before any emulation service call
public static void ensureTraceOpen(DebuggerTraceManagerService tm, Trace trace) {
    if (!tm.getOpenTraces().contains(trace)) {
        tm.openTrace(trace);
    }
}

Type guard

public static boolean isTraceOpenInTool(DebuggerTraceManagerService tm, Trace trace) {
    return trace != null && tm != null && tm.getOpenTraces().contains(trace);
}

Try / catch

try {
    emuService.startEmulation(trace, snap, monitor);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("opened in the tool")) {
        traceManager.openTrace(trace);
        emuService.startEmulation(trace, snap, monitor);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling an emulation service method (e.g. startEmulation / recordEmulation instruction) on a Trace object obtained from a file handle or a previously-closed trace, without opening it in the DebuggerTraceManagerService first. Emulating a trace after the user closed it.

Common situations: Scripts that load a trace via the domain file API but forget to openTrace() it in the tool. Reusing a stale Trace reference after the user closed the trace window. Headless/programmatic use that bypasses the trace manager.

Related errors


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