{"record":{"id":"2bfd778c34948bef","repo":"NationalSecurityAgency/ghidra","slug":"no-such-register-name","errorCode":null,"errorMessage":"No such register: {name}","messagePattern":"No such register: (.+?)","errorType":"validation","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/methods.py","lineNumber":231,"sourceCode":"\ndef find_frame_by_obj(object: TraceObject) -> Optional[gdb.Frame]:\n    return find_frame_by_pattern(FRAME_PATTERN, object, \"a StackFrame\")\n\n\ndef find_frame_by_regs_obj(object: TraceObject) -> Optional[gdb.Frame]:\n    return find_frame_by_pattern(REGS_PATTERN, object,\n                                 \"a RegisterValueContainer\")\n\n\n# Because there's no method to get a register by name....\ndef find_reg_by_name(f: gdb.Frame, name: str) -> Union[gdb.RegisterDescriptor,\n                                                       util.RegisterDesc]:\n    for reg in util.get_register_descs(f.architecture()):\n        # TODO: gdb appears to be case sensitive, but until we encounter a\n        # situation where case matters, we'll be insensitive\n        if reg.name.lower() == name.lower():\n            return reg\n    raise KeyError(f\"No such register: {name}\")\n\n\n# Oof. no gdb/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) -> gdb.Breakpoint:\n    # TODO: If len exceeds some threshold, use binary search?\n    for b in gdb.breakpoints():\n        if b.number == 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) -> gdb.Breakpoint:\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'])","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/methods.py#L213-L249","documentation":"Raised by find_reg_by_name when iterating util.get_register_descs(frame.architecture()) finds no descriptor whose name matches the requested register name (case-insensitive). The GDB Python API lacks a get-register-by-name method, so the agent scans the architecture's descriptor list; an unknown/aliased/unsupported register name leaves the loop empty. KeyError signals 'No such register: name'.","triggerScenarios":"Calling find_reg_by_name with a register name not present on the current frame's architecture — e.g. requesting 'rax' on ARM, a vendor/alias name GDB does not expose, or a name from a different ABI. Reached via register read/write method handlers that accept a client-supplied register name.","commonSituations":"Client (Ghidra UI) requests a register name valid on a different architecture; cross-architecture sessions where the trace's language differs from the target; alias/sub-register names not enumerated by gdb.RegisterDescriptor; version differences in GDB's register descriptor enumeration.","solutions":["Enumerate the available register names for the architecture and validate membership before lookup.","Map client register names through an arch-specific alias table before calling find_reg_by_name.","In the caller, catch KeyError and return an empty/'unsupported register' result to the client rather than crashing.","Confirm frame.architecture() is set (not None) before enumerating descriptors."],"exampleFix":"// before\nreg = find_reg_by_name(f, name)\n// after\navail = {r.name.lower() for r in util.get_register_descs(f.architecture())}\nif name.lower() not in avail:\n    return None  # or raise a client-facing 'unknown register'\nreg = find_reg_by_name(f, name)","handlingStrategy":"validation","validationCode":"avail = {r.name.lower() for r in util.get_register_descs(f.architecture())}\nif name.lower() not in avail:\n    return None  # unknown register for this arch\nreg = find_reg_by_name(f, name)","typeGuard":"def register_known(f: gdb.Frame, name: str) -> bool:\n    return any(r.name.lower() == name.lower()\n               for r in util.get_register_descs(f.architecture()))","tryCatchPattern":"try:\n    reg = find_reg_by_name(f, name)\nexcept KeyError:\n    # unknown register; map via alias table or return empty\n    return None","preventionTips":["enumerate register names for the architecture up front","map client/UI register names through an arch-specific alias table","confirm frame.architecture() is set before enumeration"],"tags":["ghidra","gdb","trace-rpc","key-error","registers","architecture"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}