{"record":{"id":"5c21aee7eb519282","repo":"NationalSecurityAgency/ghidra","slug":"breakpoints-breaknum-does-not-exist-5c21ae","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-lldb/src/main/py/src/ghidralldb/methods.py","lineNumber":173,"sourceCode":"\ndef find_frame_by_obj(object: TraceObject) -> lldb.SBFrame:\n    return find_frame_by_pattern(FRAME_PATTERN, object, \"a StackFrame\")\n\n\ndef find_frame_by_regs_obj(object: TraceObject) -> lldb.SBFrame:\n    return find_frame_by_pattern(REGS_PATTERN, object,\n                                 \"a RegisterValueContainer\")\n\n\n# Oof. no lldb/Python method to get breakpoint by number\n# I could keep my own cache in a dict, but why?\ndef find_bpt_by_number(breaknum: int) -> lldb.SBBreakpoint:\n    # TODO: If len exceeds some threshold, use binary search?\n    for i in range(0, util.get_target().GetNumBreakpoints()):\n        b = util.get_target().GetBreakpointAtIndex(i)\n        if b.GetID() == breaknum:\n            return b\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) -> lldb.SBBreakpoint:\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) -> lldb.SBBreakpoint:\n    return find_bpt_by_pattern(PROC_BREAK_PATTERN, object, \"a BreakpointSpec\")\n\n\n# Oof. no lldb/Python method to get breakpoint by number\n# I could keep my own cache in a dict, but why?\ndef find_wpt_by_number(watchnum: int) -> lldb.SBWatchpoint:","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/methods.py#L155-L191","documentation":"Raised by find_bpt_by_number when iterating the target's breakpoint list (util.get_target().GetBreakpointAtIndex) finds no SBBreakpoint whose GetID() equals the requested breaknum. LLDB has no direct 'get breakpoint by ID' API, so the agent scans linearly; this error fires when the ID is absent.","triggerScenarios":"find_bpt_by_pattern extracts breaknum from the Breakpoints[<breaknum>] path segment and calls find_bpt_by_number. The for-loop over GetNumBreakpoints() does not find any breakpoint whose GetID() matches.","commonSituations":"The breakpoint was deleted between trace snapshot and operation. The breaknum in the trace object path is stale or from a different target session. A race condition where breakpoints are modified concurrently.","solutions":["Refresh the trace breakpoint list with 'ghidra trace put-breaks' before operating on breakpoint paths.","Verify the breakpoint exists by checking [util.get_target().GetBreakpointAtIndex(i).GetID() for i in range(util.get_target().GetNumBreakpoints())].","Catch KeyError and report a stale-reference error to Ghidra for re-sync."],"exampleFix":"# before\nbpt = find_bpt_by_number(breaknum)\n\n# after: validate existence\nexisting_ids = {\n    util.get_target().GetBreakpointAtIndex(i).GetID()\n    for i in range(util.get_target().GetNumBreakpoints())\n}\nif breaknum not in existing_ids:\n    raise KeyError(f\"Breakpoints[{breaknum}] does not exist\")\nbpt = find_bpt_by_number(breaknum)","handlingStrategy":"try-catch","validationCode":"tgt = util.get_target()\nexisting = {tgt.GetBreakpointAtIndex(i).GetID() for i in range(tgt.GetNumBreakpoints())}\nif breaknum not in existing:\n    pass  # do not call find_bpt_by_number","typeGuard":null,"tryCatchPattern":"try:\n    bpt = find_bpt_by_number(breaknum)\nexcept KeyError:\n    refresh_breakpoints()\n    bpt = find_bpt_by_number(breaknum)","preventionTips":["Refresh the trace breakpoint list with 'ghidra trace put-breaks' after breakpoint changes.","Check the target's breakpoint IDs before operating on a breakpoint path.","Catch KeyError and trigger a trace re-sync in the method handler."],"tags":["lldb","debugger-agent","breakpoint-not-found","keyerror","trace-object"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}