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 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.

Source

Thrown at Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/methods.py:173

def find_frame_by_obj(object: TraceObject) -> lldb.SBFrame:
    return find_frame_by_pattern(FRAME_PATTERN, object, "a StackFrame")


def find_frame_by_regs_obj(object: TraceObject) -> lldb.SBFrame:
    return find_frame_by_pattern(REGS_PATTERN, object,
                                 "a RegisterValueContainer")


# Oof. no lldb/Python method to get breakpoint by number
# I could keep my own cache in a dict, but why?
def find_bpt_by_number(breaknum: int) -> lldb.SBBreakpoint:
    # TODO: If len exceeds some threshold, use binary search?
    for i in range(0, util.get_target().GetNumBreakpoints()):
        b = util.get_target().GetBreakpointAtIndex(i)
        if b.GetID() == breaknum:
            return b
    raise KeyError(f"Breakpoints[{breaknum}] does not exist")


def find_bpt_by_pattern(pattern: re.Pattern, object: TraceObject,
                        err_msg: str) -> lldb.SBBreakpoint:
    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) -> lldb.SBBreakpoint:
    return find_bpt_by_pattern(PROC_BREAK_PATTERN, object, "a BreakpointSpec")


# Oof. no lldb/Python method to get breakpoint by number
# I could keep my own cache in a dict, but why?
def find_wpt_by_number(watchnum: int) -> lldb.SBWatchpoint:

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Refresh the trace breakpoint list with 'ghidra trace put-breaks' before operating on breakpoint paths.
  2. Verify the breakpoint exists by checking [util.get_target().GetBreakpointAtIndex(i).GetID() for i in range(util.get_target().GetNumBreakpoints())].
  3. Catch KeyError and report a stale-reference error to Ghidra for re-sync.

Example fix

# before
bpt = find_bpt_by_number(breaknum)

# after: validate existence
existing_ids = {
    util.get_target().GetBreakpointAtIndex(i).GetID()
    for i in range(util.get_target().GetNumBreakpoints())
}
if breaknum not in existing_ids:
    raise KeyError(f"Breakpoints[{breaknum}] does not exist")
bpt = find_bpt_by_number(breaknum)
Defensive patterns

Strategy: try-catch

Validate before calling

tgt = util.get_target()
existing = {tgt.GetBreakpointAtIndex(i).GetID() for i in range(tgt.GetNumBreakpoints())}
if breaknum not in existing:
    pass  # do not call find_bpt_by_number

Try / catch

try:
    bpt = find_bpt_by_number(breaknum)
except KeyError:
    refresh_breakpoints()
    bpt = find_bpt_by_number(breaknum)

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/5c21aee7eb519282. Report an issue: GitHub.