{"record":{"id":"66513597f6ffa17f","repo":"NationalSecurityAgency/ghidra","slug":"no-transaction","errorCode":null,"errorMessage":"No transaction","messagePattern":"No transaction","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py","lineNumber":149,"sourceCode":"\n    def require_trace(self) -> Trace[Extra]:\n        if self.trace is None:\n            raise RuntimeError(\"No trace active\")\n        return self.trace\n\n    def require_no_trace(self) -> None:\n        if self.trace != None:\n            raise RuntimeError(\"Trace already started\")\n\n    def reset_trace(self) -> None:\n        self.trace: Optional[Trace[Extra]] = None\n        util.set_convenience_variable('_ghidra_tracing', \"false\")\n        self.reset_tx()\n\n    def require_tx(self) -> Tuple[Trace, Transaction]:\n        trace = self.require_trace()\n        if self.tx is None:\n            raise RuntimeError(\"No transaction\")\n        return trace, self.tx\n\n    def require_no_tx(self) -> None:\n        if self.tx != None:\n            raise RuntimeError(\"Transaction already started\")\n\n    def reset_tx(self) -> None:\n        self.tx: Optional[Transaction] = None\n\n\nSTATE = State()\n\n\ndef ghidra_trace_connect(address: Optional[str] = None) -> None:\n    \"\"\"Connect Python to Ghidra for tracing.\n\n    Address must be of the form 'host:port'\n    \"\"\"","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py#L131-L167","documentation":"Raised by State.require_tx() (commands.py:148-149) when a trace is active but no Trace transaction (STATE.tx) is open. Ghidra traces are mutated inside Transaction objects; mutating the trace tree, memory, or registers outside a transaction is illegal. require_tx() is the precondition gate for nearly every write command.","triggerScenarios":"Calling putmem/putmem_state/delmem/retain_values/etc. (all of which begin with STATE.require_tx()) before opening a transaction with ghidra_trace_tx_start; calling them after ghidra_trace_tx_commit or ghidra_trace_tx_abort reset STATE.tx to None; calling a write command after a trace was just started but no tx was opened.","commonSituations":"Script that calls ghidra_trace_start then immediately ghidra_trace_putmem, skipping the tx_start step; stale session after a commit where the developer assumed the transaction auto-reopened; copy/paste from a recipe that omitted the transaction bracket.","solutions":["Wrap every mutating command pair in ghidra_trace_tx_start('description') ... ghidra_trace_tx_commit().","If unsure whether a tx is open, guard it: call require_no_tx-free logic by committing any open tx first, then opening a fresh one.","Reset session state with ghidra_trace_disconnect/stop and replay the full connect->start->tx_start sequence."],"exampleFix":"// before\nghidra_trace_putmem(addr, length)   # RuntimeError: No transaction\n\n// after\nghidra_trace_tx_start('record mem')\nghidra_trace_putmem(addr, length)\nghidra_trace_tx_commit()","handlingStrategy":"validation","validationCode":"from ghidradbg.commands import STATE\nif getattr(STATE, 'tx', None) is None:\n    raise RuntimeError('open a transaction first with ghidra_trace_tx_start')","typeGuard":"def tx_is_open() -> bool:\n    from ghidradbg.commands import STATE\n    return getattr(STATE, 'tx', None) is not None and getattr(STATE, 'trace', None) is not None","tryCatchPattern":"try:\n    ghidra_trace_putmem(addr, length)\nexcept RuntimeError as e:\n    if 'No transaction' in str(e):\n        ghidra_trace_tx_start('retry')\n        ghidra_trace_putmem(addr, length)\n        ghidra_trace_tx_commit()\n    else:\n        raise","preventionTips":["Wrap every mutating command in tx_start/tx_commit.","Use a context-manager helper so commit/abort always fires.","Never assume a tx auto-reopens after commit."],"tags":["transaction","trace-lifecycle","debugger-agent","ghidra"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}