{"record":{"id":"1fad6e21a012c9d9","repo":"NationalSecurityAgency/ghidra","slug":"transaction-already-started-1fad6e","errorCode":null,"errorMessage":"Transaction already started","messagePattern":"Transaction already started","errorType":"validation","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py","lineNumber":131,"sourceCode":"\n    def require_no_trace(self) -> None:\n        if self.trace is not 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[Extra], 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 is not 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\nif __name__ == '__main__':\n    lldb.SBDebugger.InitializeWithErrorHandling()\n    lldb.debugger = lldb.SBDebugger.Create()\nelif lldb.debugger:\n    lldb.debugger.HandleCommand(\n        'command container add -h \"Commands for connecting to Ghidra\" ghidra')\n    lldb.debugger.HandleCommand(\n        'command container add -h \"Commands for exporting data to a Ghidra trace\" ghidra trace')\n    lldb.debugger.HandleCommand(\n        'command container add -h \"Utility commands for testing with Ghidra\" ghidra util')\n","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py#L113-L149","documentation":"Raised by State.require_no_tx in the Ghidra LLDB agent when STATE.tx is already set — i.e. a transaction is already open. The start-tx command (commands.py:525 calls require_no_tx) calls this to prevent nesting two transactions; an existing open transaction is rejected with RuntimeError.","triggerScenarios":"Running the start-tx command a second time without first committing/closing the existing transaction. The start-tx command asserts require_no_tx before opening a new Transaction.","commonSituations":"User runs 'ghidra_trace_tx_start' twice; previous tx was not committed (ghidra_trace_tx_commit); script opens a second tx without closing the first.","solutions":["Commit/close the current transaction (ghidra_trace_tx_commit, commands.py:542) before starting a new one.","Use STATE.require_trace().open_tx(description) as a context manager so the tx always closes on block exit.","Catch RuntimeError and hint 'transaction already started; run ghidra_trace_tx_commit first'.","Ensure reset_tx is invoked after commit so STATE.tx returns to None."],"exampleFix":"// before\nSTATE.require_no_tx()\nSTATE.tx = STATE.require_trace().start_tx(description, undoable=False)\n// after\nif STATE.tx is not None:\n    STATE.require_tx()[1].commit()\n    STATE.reset_tx()\nSTATE.require_no_tx()\nSTATE.tx = STATE.require_trace().start_tx(description, undoable=False)","handlingStrategy":"validation","validationCode":"if STATE.tx is not None:\n    STATE.require_tx()[1].commit()\n    STATE.reset_tx()\nSTATE.require_no_tx()\nSTATE.tx = STATE.require_trace().start_tx(description, undoable=False)","typeGuard":"def no_tx_open() -> bool:\n    return STATE.tx is None","tryCatchPattern":"try:\n    STATE.require_no_tx()\nexcept RuntimeError:\n    print(\"Transaction already started; run ghidra_trace_tx_commit first\")\n    return","preventionTips":["commit/close the current tx before starting a new one","use open_tx context managers","call reset_tx after commit"],"tags":["ghidra","lldb","runtime-error","state-machine","transaction"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}