NationalSecurityAgency/ghidra · error · RuntimeError
No transaction
Error message
No transaction
What it means
Raised by State.require_tx when STATE.tx is None. Transactions wrap trace mutations; they are opened via trace.open_tx (used in 'ghidra trace tx-start' / open_tracked_tx). Any method that modifies the trace calls require_tx to ensure a transaction is active before writing.
Source
Thrown at Ghidra/Debug/Debugger-agent-x64dbg/src/main/py/src/ghidraxdbg/commands.py:146
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] = None
STATE = State()
def ghidra_trace_connect(address: Optional[str] = None) -> None:
"""Connect Python to Ghidra for tracing.
Address must be of the form 'host:port'
"""View on GitHub (pinned to d5f144c24d)
Solutions
- Open a transaction with 'ghidra trace tx-start <description>' before issuing mutation commands.
- Use the open_tracked_tx context manager to ensure the transaction lifecycle is correct.
- Check STATE.tx is not None before calling require_tx-dependent commands.
Example fix
# before: mutation without transaction
trace, tx = STATE.require_tx() # tx is None
# after: open transaction first
with commands.open_tracked_tx('My Operation'):
trace, tx = STATE.require_tx()
# ... perform trace mutations ... Defensive patterns
Strategy: validation
Validate before calling
if STATE.tx is None:
raise RuntimeError("No transaction; run 'ghidra trace tx-start' or use open_tracked_tx first") Type guard
def has_tx() -> bool:
return getattr(STATE, 'tx', None) is not None Try / catch
try:
trace, tx = STATE.require_tx()
except RuntimeError:
with commands.open_tracked_tx('Auto Transaction'):
trace, tx = STATE.require_tx()
# ... perform mutations ... Prevention
- Open a transaction with 'ghidra trace tx-start' or open_tracked_tx before mutation commands.
- Use the open_tracked_tx context manager to manage transaction lifecycle automatically.
- Check STATE.tx is not None before calling require_tx-dependent operations.
When it happens
Trigger: A trace-mutation command calls STATE.require_tx() before 'ghidra trace tx-start' (or trace.open_tx) has opened a transaction. This also fires after tx-stop/reset_tx clears the transaction.
Common situations: User issued 'ghidra trace put-*' or other mutation commands without first opening a transaction. The transaction was committed/stopped and not reopened before the next mutation. reset_tx was called (e.g. by reset_trace) and mutations were attempted.
Related errors
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/3d0fadf6403cd405.
Report an issue: GitHub.