NationalSecurityAgency/ghidra · error · RuntimeError
No transaction
Error message
No transaction
What it means
Raised by State.require_tx in the Ghidra LLDB agent when STATE.tx is None — i.e. no transaction is currently open on the trace. Commands that mutate the trace (putmem, regs, objects, snapshots written under tx) call require_tx to obtain a (trace, tx) pair; without an open transaction, writes are disallowed. RuntimeError signals a lifecycle precondition: a transaction must be started (commands.py:525-526, start_tx) before mutating commands.
Source
Thrown at Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py:126
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
STATE = State()
if __name__ == '__main__':
lldb.SBDebugger.InitializeWithErrorHandling()
lldb.debugger = lldb.SBDebugger.Create()
elif lldb.debugger:
lldb.debugger.HandleCommand(
'command container add -h "Commands for connecting to Ghidra" ghidra')View on GitHub (pinned to d5f144c24d)
Solutions
- Open a transaction (ghidra_trace_tx_start) before any mutating command, and commit/close it (ghidra_trace_tx_commit) when done.
- Prefer STATE.require_trace().open_tx(description) as a context manager so the tx always closes.
- Catch RuntimeError and hint 'no transaction; run ghidra_trace_tx_start'.
- Ensure tx is reset (reset_tx) after commit so stale state does not confuse subsequent checks.
Example fix
// before
trace, tx = STATE.require_tx()
// after
if STATE.tx is None:
print("No transaction. Run: ghidra_trace_tx_start <description>")
return
trace, tx = STATE.require_tx() Defensive patterns
Strategy: validation
Validate before calling
if STATE.tx is None:
print("No transaction. Run: ghidra_trace_tx_start <description>")
return
trace, tx = STATE.require_tx() Type guard
def tx_open() -> bool:
return STATE.tx is not None Try / catch
try:
trace, tx = STATE.require_tx()
except RuntimeError:
print("No transaction; run ghidra_trace_tx_start first")
return Prevention
- open a transaction before mutating commands
- prefer open_tx context managers to guarantee close
- reset_tx after commit
When it happens
Trigger: Running a mutating trace command (e.g. putmem, putregs, object creation) outside of a started transaction — before 'ghidra_trace_tx_start' opened one. require_tx also internally calls require_trace, so a missing trace surfaces as 196 first. Reached by the many commands calling STATE.require_tx().
Common situations: User issued put/record commands before opening a transaction; transaction was committed/closed and user continued mutating; script that writes without tx.
Related errors
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/092436636d6239b8.
Report an issue: GitHub.