{"record":{"id":"867cea829ff5a13f","repo":"NationalSecurityAgency/ghidra","slug":"trace-already-started","errorCode":null,"errorMessage":"Trace already started","messagePattern":"Trace already started","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py","lineNumber":139,"sourceCode":"            raise RuntimeError(\"Not connected\")\n        return self.client\n\n    def require_no_client(self) -> None:\n        if self.client != None:\n            raise RuntimeError(\"Already connected\")\n\n    def reset_client(self) -> None:\n        self.client: Optional[Client] = None\n        self.reset_trace()\n\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","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py#L121-L157","documentation":"Raised by State.require_no_trace() when the Ghidra debug agent already has an active Trace object (STATE.trace is not None). The guard enforces single-trace ownership: only one trace may exist per connected client at a time. This prevents overlapping start_trace calls from corrupting the trace lifecycle and the '_ghidra_tracing' convenience variable.","triggerScenarios":"Calling ghidra_trace_start(name) a second time without first calling ghidra_trace_stop() or ghidra_trace_disconnect(); calling start_trace() directly while a prior create_trace() result still lives in STATE.trace; invoking any command that wraps require_no_trace() (ghidra_trace_start at commands.py:271) when a trace is already live.","commonSituations":"Re-running a trace script in the same dbgeng/cdb/WinDbg session after the first run completed but ghidra_trace_stop was skipped; lingering trace after a debugger crash or abrupt disconnect where reset_trace() never fired; batch scripts that loop create-and-trace without teardown.","solutions":["Call ghidra_trace_stop() (or ghidra_trace_disconnect()) before starting a new trace, so STATE.trace is reset to None.","If you do not care about preserving the current trace, use ghidra_trace_restart(name) instead of ghidra_trace_start — it closes and resets the existing trace first (commands.py:282-290).","Check the '_ghidra_tracing' convenience variable (set false by reset_trace) before issuing start; if it is 'true', tear down first."],"exampleFix":"// before\nghidra_trace_start('myapp')   # fails if a trace already exists\nghidra_trace_start('myapp')\n\n// after\nif STATE.trace is not None:\n    ghidra_trace_stop()\nghidra_trace_start('myapp')\n# or simply:\nghidra_trace_restart('myapp')","handlingStrategy":"validation","validationCode":"from ghidradbg.commands import STATE\nif getattr(STATE, 'trace', None) is not None:\n    ghidra_trace_stop()   # tear down before starting a new one","typeGuard":"def trace_is_idle() -> bool:\n    from ghidradbg.commands import STATE\n    return getattr(STATE, 'trace', None) is None","tryCatchPattern":"try:\n    ghidra_trace_start(name)\nexcept RuntimeError as e:\n    if 'Trace already started' in str(e):\n        ghidra_trace_restart(name)   # or stop then start\n    else:\n        raise","preventionTips":["Always pair ghidra_trace_start with a ghidra_trace_stop in a try/finally.","Prefer ghidra_trace_restart when you may already have a trace.","Check the '_ghidra_tracing' convenience variable before starting."],"tags":["state","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"}