NationalSecurityAgency/ghidra · error · KeyError
Breakpoints[{breaknum}] does not exist
Error message
Breakpoints[{breaknum}] does not exist What it means
Raised by find_bpt_by_number() (methods.py:183-184) as a KeyError when dbg()._control.GetBreakpointById(breaknum) raises E_NOINTERFACE_Error — the dbgeng COM control has no breakpoint with that numeric ID. The KeyError shape lets callers do dict-style 'does this breakpoint exist?' lookups.
Source
Thrown at Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py:184
raise TypeError(f"{object} is not {err_msg}")
pnum = int(mat['procnum'])
tnum = int(mat['tnum'])
level = int(mat['level'])
find_proc_by_num(pnum)
find_thread_by_num(tnum)
return find_frame_by_level(level)
def find_frame_by_obj(object: TraceObject) -> DbgEng._DEBUG_STACK_FRAME:
return find_frame_by_pattern(FRAME_PATTERN, object, "a StackFrame")
def find_bpt_by_number(breaknum: int) -> DbgEng.IDebugBreakpoint:
try:
bp = dbg()._control.GetBreakpointById(breaknum)
return bp
except exception.E_NOINTERFACE_Error:
raise KeyError(f"Breakpoints[{breaknum}] does not exist")
def find_bpt_by_pattern(pattern: re.Pattern, object: TraceObject,
err_msg: str) -> DbgEng.IDebugBreakpoint:
mat = pattern.fullmatch(object.path)
if mat is None:
raise TypeError(f"{object} is not {err_msg}")
breaknum = int(mat['breaknum'])
return find_bpt_by_number(breaknum)
def find_bpt_by_obj(object: TraceObject) -> DbgEng.IDebugBreakpoint:
return find_bpt_by_pattern(PROC_BREAKBPT_PATTERN, object, "a BreakpointSpec")
def find_evt_by_number(eventnum: int) -> DbgEng._DEBUG_SPECIFIC_FILTER_PARAMETERS:
try:
return util.GetSpecificFilterParameters(eventnum, 1)View on GitHub (pinned to d5f144c24d)
Solutions
- Re-enumerate breakpoints (dbg()._control.EnumerateBreakpoints / the agent's Breakpoints container) to get fresh IDs before lookup.
- Wrap the lookup in a try/except KeyError to handle a missing breakpoint gracefully.
- Avoid caching breakpoint IDs across process create/restart boundaries.
Example fix
// before
bp = find_bpt_by_number(cached_id) # KeyError if deleted
// after
try:
bp = find_bpt_by_number(cached_id)
except KeyError:
# re-enumerate and use a valid id
bp = find_bpt_by_number(fresh_id) Defensive patterns
Strategy: try-catch
Validate before calling
def bpt_exists(breaknum) -> bool:
try:
dbg()._control.GetBreakpointById(breaknum)
return True
except exception.E_NOINTERFACE_Error:
return False
if not bpt_exists(breaknum):
raise KeyError(f'no breakpoint {breaknum}; re-enumerate') Type guard
def bpt_exists(breaknum) -> bool:
from ghidradbg.util import dbg
from ghidradbg import exception
try:
dbg()._control.GetBreakpointById(breaknum)
return True
except exception.E_NOINTERFACE_Error:
return False Try / catch
try:
bp = find_bpt_by_number(breaknum)
except KeyError as e:
if 'does not exist' in str(e):
# re-enumerate and pick a valid id
raise KeyError(f'stale breakpoint id {breaknum}; refresh from the Breakpoints container') from e
raise Prevention
- Never cache breakpoint IDs across process restarts.
- Re-enumerate breakpoints before lookup.
- Treat missing breakpoints as recoverable via KeyError handling.
When it happens
Trigger: Looking up a breakpoint ID that was deleted or never created; referencing a breakpoint number after the target process restarted (IDs reset); stale breakpoint number captured from a previous session.
Common situations: Script caching breakpoint IDs across a process restart; UI referencing a breakpoint removed by the user; off-by-one in breakpoint enumeration.
Related errors
- Events[{eventnum}] does not exist
- Block model not found: " + modelName
- Unsupported value: {}
- Invalid value for {}
- No such address space: %s
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/2142761e65ed51c2.
Report an issue: GitHub.