{"record":{"id":"6970c26f57425d4e","repo":"NationalSecurityAgency/ghidra","slug":"cannot-emulate-a-trace-unless-it-s-opened-in-the-t","errorCode":null,"errorMessage":"Cannot emulate a trace unless it's opened in the tool.","messagePattern":"Cannot emulate a trace unless it's opened in the tool\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java","lineNumber":898,"sourceCode":"\n\tprotected void createRegisterSpaces(Trace trace, TraceSchedule time, TaskMonitor monitor) {\n\t\tif (trace.getObjectManager().getRootObject() == null) {\n\t\t\treturn;\n\t\t}\n\t\t// Cause object-register support to copy values into new register spaces\n\t\t// TODO: I wish this were not necessary\n\t\tmonitor.setMessage(\"Creating register spaces\");\n\t\ttry (Transaction tx = trace.openTransaction(\"Prepare emulation\")) {\n\t\t\tfor (TraceThread thread : time.getThreads(trace)) {\n\t\t\t\ttrace.getMemoryManager().getMemoryRegisterSpace(thread, 0, true);\n\t\t\t}\n\t\t}\n\t\ttrace.clearUndo();\n\t}\n\n\tprotected void requireOpen(Trace trace) {\n\t\tif (!traceManager.getOpenTraces().contains(trace)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\"Cannot emulate a trace unless it's opened in the tool.\");\n\t\t}\n\t}\n\n\tclass TraceMappingWaiter extends CompletableFuture<Void>\n\t\t\timplements DebuggerStaticMappingChangeListener {\n\t\tprivate final Trace trace;\n\n\t\tpublic TraceMappingWaiter(Trace trace) {\n\t\t\tthis.trace = trace;\n\t\t}\n\n\t\t@Override\n\t\tpublic void mappingsChanged(Set<Trace> affectedTraces, Set<Program> affectedPrograms) {\n\t\t\tif (affectedTraces.contains(trace)) {\n\t\t\t\tcomplete(null);\n\t\t\t}\n\t\t}","sourceCodeStart":880,"sourceCodeEnd":916,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/DebuggerEmulationServicePlugin.java#L880-L916","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Open the trace in the tool via DebuggerTraceManagerService.openTrace(trace) before requesting emulation.","Guard the call by checking traceManager.getOpenTraces().contains(trace).","Re-open the trace if it was closed, then retry emulation."],"exampleFix":"// before\nemuService.startEmulation(trace, snap, monitor); // throws if not opened\n\n// after\nif (!traceManager.getOpenTraces().contains(trace)) {\n    traceManager.openTrace(trace);\n}\nemuService.startEmulation(trace, snap, monitor);","handlingStrategy":"validation","validationCode":"// Run before any emulation service call\npublic static void ensureTraceOpen(DebuggerTraceManagerService tm, Trace trace) {\n    if (!tm.getOpenTraces().contains(trace)) {\n        tm.openTrace(trace);\n    }\n}","typeGuard":"public static boolean isTraceOpenInTool(DebuggerTraceManagerService tm, Trace trace) {\n    return trace != null && tm != null && tm.getOpenTraces().contains(trace);\n}","tryCatchPattern":"try {\n    emuService.startEmulation(trace, snap, monitor);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"opened in the tool\")) {\n        traceManager.openTrace(trace);\n        emuService.startEmulation(trace, snap, monitor);\n    } else throw e;\n}","preventionTips":["Always open a trace in the trace manager before requesting emulation.","In scripts, treat openTrace() as the prerequisite step for any emulation/platform/mapping API.","Drop stale Trace references after close events."],"tags":["emulation","trace-manager","lifecycle","precondition"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}