NationalSecurityAgency/ghidra · error · RuntimeError
Trace already started
Error message
Trace already started
What it means
Raised by State.require_no_trace() when the Ghidra debug agent already has an active Trace object (STATE.trace is not None). The guard enforces single-trace ownership: only one trace may exist per connected client at a time. This prevents overlapping start_trace calls from corrupting the trace lifecycle and the '_ghidra_tracing' convenience variable.
Source
Thrown at Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py:139
raise RuntimeError("Not connected")
return self.client
def require_no_client(self) -> None:
if self.client != None:
raise RuntimeError("Already connected")
def reset_client(self) -> None:
self.client: Optional[Client] = None
self.reset_trace()
def require_trace(self) -> Trace[Extra]:
if self.trace is None:
raise RuntimeError("No trace active")
return self.trace
def require_no_trace(self) -> None:
if self.trace != None:
raise RuntimeError("Trace already started")
def reset_trace(self) -> None:
self.trace: Optional[Trace[Extra]] = None
util.set_convenience_variable('_ghidra_tracing', "false")
self.reset_tx()
def require_tx(self) -> Tuple[Trace, Transaction]:
trace = self.require_trace()
if self.tx is None:
raise RuntimeError("No transaction")
return trace, self.tx
def require_no_tx(self) -> None:
if self.tx != None:
raise RuntimeError("Transaction already started")
def reset_tx(self) -> None:
self.tx: Optional[Transaction] = NoneView on GitHub (pinned to d5f144c24d)
Solutions
- Call ghidra_trace_stop() (or ghidra_trace_disconnect()) before starting a new trace, so STATE.trace is reset to None.
- If you do not care about preserving the current trace, use ghidra_trace_restart(name) instead of ghidra_trace_start — it closes and resets the existing trace first (commands.py:282-290).
- Check the '_ghidra_tracing' convenience variable (set false by reset_trace) before issuing start; if it is 'true', tear down first.
Example fix
// before
ghidra_trace_start('myapp') # fails if a trace already exists
ghidra_trace_start('myapp')
// after
if STATE.trace is not None:
ghidra_trace_stop()
ghidra_trace_start('myapp')
# or simply:
ghidra_trace_restart('myapp') Defensive patterns
Strategy: validation
Validate before calling
from ghidradbg.commands import STATE
if getattr(STATE, 'trace', None) is not None:
ghidra_trace_stop() # tear down before starting a new one Type guard
def trace_is_idle() -> bool:
from ghidradbg.commands import STATE
return getattr(STATE, 'trace', None) is None Try / catch
try:
ghidra_trace_start(name)
except RuntimeError as e:
if 'Trace already started' in str(e):
ghidra_trace_restart(name) # or stop then start
else:
raise Prevention
- Always pair ghidra_trace_start with a ghidra_trace_stop in a try/finally.
- Prefer ghidra_trace_restart when you may already have a trace.
- Check the '_ghidra_tracing' convenience variable before starting.
When it happens
Trigger: Calling ghidra_trace_start(name) a second time without first calling ghidra_trace_stop() or ghidra_trace_disconnect(); calling start_trace() directly while a prior create_trace() result still lives in STATE.trace; invoking any command that wraps require_no_trace() (ghidra_trace_start at commands.py:271) when a trace is already live.
Common situations: Re-running a trace script in the same dbgeng/cdb/WinDbg session after the first run completed but ghidra_trace_stop was skipped; lingering trace after a debugger crash or abrupt disconnect where reset_trace() never fired; batch scripts that loop create-and-trace without teardown.
Related errors
- No transaction
- Transaction already started
- 'ghidra_trace_connect': missing required argument 'address'
- Invalid argument: {key_list[0]}
- Usage: ghidra trace disassemble ADDRESS
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/867cea829ff5a13f.
Report an issue: GitHub.