NationalSecurityAgency/ghidra · error · RuntimeError

Trace already started

Error message

Trace already started

What it means

Raised by State.require_no_trace in the Ghidra LLDB agent when STATE.trace is already set — i.e. a trace is already active. The start-trace command (commands.py:415 calls require_no_trace) calls this to prevent starting a second trace over an existing one; an existing trace is rejected with RuntimeError.

Source

Thrown at Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py:116

            raise RuntimeError("Not connected")
        return self.client

    def require_no_client(self) -> None:
        if self.client is not 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 is not 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[Extra], 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 is not None:
            raise RuntimeError("Transaction already started")

    def reset_tx(self) -> None:
        self.tx: Optional[Transaction] = None

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Run the stop-trace command (ghidra_trace_stop, commands.py:432 close) before starting again.
  2. Guard scripts: if STATE.trace is not None, stop/close it first.
  3. Catch RuntimeError and hint 'trace already started; run ghidra_trace_stop first'.
  4. Ensure stop is called on script exit to reset STATE.trace.

Example fix

// before
STATE.require_no_trace()
STATE.trace = STATE.require_client().create_trace(...)
// after
if STATE.trace is not None:
    STATE.require_trace().close()
    STATE.reset_trace()
STATE.require_no_trace()
STATE.trace = STATE.require_client().create_trace(...)
Defensive patterns

Strategy: validation

Validate before calling

if STATE.trace is not None:
    STATE.require_trace().close()
    STATE.reset_trace()
STATE.require_no_trace()
STATE.trace = STATE.require_client().create_trace(...)

Type guard

def no_trace_active() -> bool:
    return STATE.trace is None

Try / catch

try:
    STATE.require_no_trace()
except RuntimeError:
    print("Trace already started; run ghidra_trace_stop first")
    return

Prevention

When it happens

Trigger: Running the start-trace command a second time without first closing/stopping the existing trace. The start command asserts require_no_trace before creating a new Trace.

Common situations: User runs 'ghidra_trace_start' twice; previous trace was not closed (ghidra_trace_stop/trace.close not run); script re-starts without teardown.

Related errors


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