NationalSecurityAgency/ghidra · error · KeyError
Processes[{proc.GetProcessID()}].Threads[{tnum}] does not ex
Error message
Processes[{proc.GetProcessID()}].Threads[{tnum}] does not exist What it means
Raised by find_thread_by_num when iterating proc.threads finds no thread whose GetThreadID() matches the requested tnum. The Ghidra LLDB agent resolves trace object paths of the form Processes[<procnum>].Threads[<tnum>] to live LLDB SBThread objects; this error fires when the thread ID extracted from the path does not exist in the current process thread list.
Source
Thrown at Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/methods.py:117
def find_proc_by_mem_obj(object: TraceObject) -> lldb.SBProcess:
return find_proc_by_pattern(object, MEMORY_PATTERN, "a Memory")
def find_proc_by_modules_obj(object: TraceObject) -> lldb.SBProcess:
return find_proc_by_pattern(object, MODULES_PATTERN, "a ModuleContainer")
def find_proc_by_frame(object: TraceObject) -> lldb.SBProcess:
return find_proc_by_pattern(object, FRAME_PATTERN, "a StaclFrame")
def find_thread_by_num(proc: lldb.SBThread, tnum: int) -> lldb.SBThread:
for t in proc.threads:
if t.GetThreadID() == tnum:
return t
raise KeyError(
f"Processes[{proc.GetProcessID()}].Threads[{tnum}] does not exist")
def find_thread_by_pattern(pattern: re.Pattern, object: TraceObject,
err_msg: str) -> lldb.SBThread:
mat = pattern.fullmatch(object.path)
if mat is None:
raise TypeError(f"{object} is not {err_msg}")
procnum = int(mat['procnum'])
tnum = int(mat['tnum'])
proc = find_proc_by_num(procnum)
return find_thread_by_num(proc, tnum)
def find_thread_by_obj(object: TraceObject) -> lldb.SBThread:
return find_thread_by_pattern(THREAD_PATTERN, object, "a Thread")
View on GitHub (pinned to d5f144c24d)
Solutions
- Re-snapshot the trace so object paths reflect the live thread set (e.g. re-run 'ghidra trace tx-start' followed by the appropriate put-* commands).
- Verify the thread still exists by checking proc.threads for the matching GetThreadID() before invoking the trace method.
- Catch KeyError in the method handler and return a trace-rpc error so Ghidra's UI can re-sync its object tree.
Example fix
# before: stale tnum passed blindly
proc = find_proc_by_num(procnum)
thread = find_thread_by_num(proc, tnum)
# after: verify existence first
tids = [t.GetThreadID() for t in proc.threads]
if tnum not in tids:
raise KeyError(f"Processes[{proc.GetProcessID()}].Threads[{tnum}] does not exist")
thread = next(t for t in proc.threads if t.GetThreadID() == tnum) Defensive patterns
Strategy: try-catch
Validate before calling
proc = find_proc_by_num(procnum)
tids = {t.GetThreadID() for t in proc.threads}
if tnum not in tids:
# do not call find_thread_by_num; refresh trace or report error
pass Try / catch
try:
thread = find_thread_by_num(proc, tnum)
except KeyError:
# thread no longer exists; refresh trace and retry or report
refresh_trace_threads(proc)
thread = find_thread_by_num(proc, tnum) Prevention
- Refresh the trace before operating on thread paths after the target continues or changes state.
- Cache thread IDs at snapshot time and compare against proc.threads before use.
- Catch KeyError in RPC method handlers and return a structured error so Ghidra can re-sync.
When it happens
Trigger: A Ghidra trace method (e.g. activate, read_reg, step) calls find_thread_by_pattern, which extracts tnum from the Threads[<tnum>] segment of the TraceObject path and passes it to find_thread_by_num. The LLDB SBProcess.threads collection contains no SBThread whose GetThreadID() equals that integer.
Common situations: The target thread has exited or been terminated between trace snapshot and operation. A multi-threaded target where threads are dynamically created and destroyed left stale IDs in the trace. The process state changed (e.g. after a continue or kill) without refreshing the trace.
Related errors
- Breakpoints[{breaknum}] does not exist
- Watchpoints[{watchnum}] does not exist
- Usage: ghidra trace disassemble ADDRESS
- Usage: ghidra trace put-processes
- Usage: ghidra trace put-available
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/8b5ff4d212e83f5d.
Report an issue: GitHub.