{"record":{"id":"2142761e65ed51c2","repo":"NationalSecurityAgency/ghidra","slug":"breakpoints-breaknum-does-not-exist","errorCode":null,"errorMessage":"Breakpoints[{breaknum}] does not exist","messagePattern":"Breakpoints\\[(.+?)\\] does not exist","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py","lineNumber":184,"sourceCode":"        raise TypeError(f\"{object} is not {err_msg}\")\n    pnum = int(mat['procnum'])\n    tnum = int(mat['tnum'])\n    level = int(mat['level'])\n    find_proc_by_num(pnum)\n    find_thread_by_num(tnum)\n    return find_frame_by_level(level)\n\n\ndef find_frame_by_obj(object: TraceObject) -> DbgEng._DEBUG_STACK_FRAME:\n    return find_frame_by_pattern(FRAME_PATTERN, object, \"a StackFrame\")\n\n\ndef find_bpt_by_number(breaknum: int) -> DbgEng.IDebugBreakpoint:\n    try:\n        bp = dbg()._control.GetBreakpointById(breaknum)\n        return bp\n    except exception.E_NOINTERFACE_Error:\n        raise KeyError(f\"Breakpoints[{breaknum}] does not exist\")\n\n\ndef find_bpt_by_pattern(pattern: re.Pattern, object: TraceObject,\n                        err_msg: str) -> DbgEng.IDebugBreakpoint:\n    mat = pattern.fullmatch(object.path)\n    if mat is None:\n        raise TypeError(f\"{object} is not {err_msg}\")\n    breaknum = int(mat['breaknum'])\n    return find_bpt_by_number(breaknum)\n\n\ndef find_bpt_by_obj(object: TraceObject) -> DbgEng.IDebugBreakpoint:\n    return find_bpt_by_pattern(PROC_BREAKBPT_PATTERN, object, \"a BreakpointSpec\")\n\n\ndef find_evt_by_number(eventnum: int) -> DbgEng._DEBUG_SPECIFIC_FILTER_PARAMETERS:\n    try:\n        return util.GetSpecificFilterParameters(eventnum, 1)","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py#L166-L202","documentation":"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.","triggerScenarios":"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.","commonSituations":"Script caching breakpoint IDs across a process restart; UI referencing a breakpoint removed by the user; off-by-one in breakpoint enumeration.","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."],"exampleFix":"// before\nbp = find_bpt_by_number(cached_id)   # KeyError if deleted\n\n// after\ntry:\n    bp = find_bpt_by_number(cached_id)\nexcept KeyError:\n    # re-enumerate and use a valid id\n    bp = find_bpt_by_number(fresh_id)","handlingStrategy":"try-catch","validationCode":"def bpt_exists(breaknum) -> bool:\n    try:\n        dbg()._control.GetBreakpointById(breaknum)\n        return True\n    except exception.E_NOINTERFACE_Error:\n        return False\n\nif not bpt_exists(breaknum):\n    raise KeyError(f'no breakpoint {breaknum}; re-enumerate')","typeGuard":"def bpt_exists(breaknum) -> bool:\n    from ghidradbg.util import dbg\n    from ghidradbg import exception\n    try:\n        dbg()._control.GetBreakpointById(breaknum)\n        return True\n    except exception.E_NOINTERFACE_Error:\n        return False","tryCatchPattern":"try:\n    bp = find_bpt_by_number(breaknum)\nexcept KeyError as e:\n    if 'does not exist' in str(e):\n        # re-enumerate and pick a valid id\n        raise KeyError(f'stale breakpoint id {breaknum}; refresh from the Breakpoints container') from e\n    raise","preventionTips":["Never cache breakpoint IDs across process restarts.","Re-enumerate breakpoints before lookup.","Treat missing breakpoints as recoverable via KeyError handling."],"tags":["breakpoint","com","lookup","ghidra"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}