{"record":{"id":"a540c05b2e5d6c48","repo":"NationalSecurityAgency/ghidra","slug":"object-object-does-not-support-description-level","errorCode":null,"errorMessage":"Object {object} does not support description level","messagePattern":"Object (.+?) does not support description level","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/util.py","lineNumber":285,"sourceCode":"\n\ndef get_eval(expr: str) -> lldb.SBValue:\n    eval = get_target().EvaluateExpression(expr)\n    if eval.GetError().Fail():\n        raise ValueError(eval.GetError().GetCString())\n    return eval\n\n\ndef get_description(object: Union[\n        lldb.SBThread, lldb.SBBreakpoint, lldb.SBWatchpoint, lldb.SBEvent],\n        level: Optional[int] = None) -> str:\n    stream = lldb.SBStream()\n    if level is None:\n        object.GetDescription(stream)\n    elif isinstance(object, lldb.SBWatchpoint):\n        object.GetDescription(stream, level)\n    else:\n        raise ValueError(f\"Object {object} does not support description level\")\n    return escape_ansi(stream.GetData())\n\n\nconv_map: Dict[str, str] = {}\n\n\ndef get_convenience_variable(id: str) -> str:\n    # val = get_target().GetEnvironment().Get(id)\n    if id not in conv_map:\n        return \"auto\"\n    val = conv_map[id]\n    if val is None:\n        return \"auto\"\n    return val\n\n\ndef set_convenience_variable(id: str, value: str) -> None:\n    # env = get_target().GetEnvironment()","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/util.py#L267-L303","documentation":"Raised by get_description when a non-SBWatchpoint object is passed with a non-None level parameter. Only lldb.SBWatchpoint.GetDescription accepts a second 'level' argument; SBThread, SBBreakpoint, and SBEvent ignore the level, so the function guards against unsupported types.","triggerScenarios":"get_description is called with level set (not None) and the object is an SBThread, SBBreakpoint, or SBEvent (i.e. not an SBWatchpoint). The elif branch falls through to the raise.","commonSituations":"Caller assumes all LLDB description-capable objects support the level parameter. A watchpoint-specific code path was generalized to other object types without accounting for the API difference.","solutions":["Pass level=None when calling get_description for non-SBWatchpoint objects.","Check isinstance(object, lldb.SBWatchpoint) before passing a level value.","Restructure to call object.GetDescription(stream) for non-watchpoint types and object.GetDescription(stream, level) only for watchpoints."],"exampleFix":"# before: level passed for non-watchpoint\nlvl = some_level\ndesc = get_description(thread_obj, level=lvl)  # SBThread does not support level\n\n# after: only pass level for watchpoints\ndesc = get_description(\n    thread_obj,\n    level=lvl if isinstance(thread_obj, lldb.SBWatchpoint) else None,\n)","handlingStrategy":"type-guard","validationCode":"if level is not None and not isinstance(object, lldb.SBWatchpoint):\n    level = None  # or raise early","typeGuard":"def supports_description_level(obj) -> bool:\n    return isinstance(obj, lldb.SBWatchpoint)","tryCatchPattern":"try:\n    desc = get_description(obj, level=level)\nexcept ValueError as e:\n    if 'does not support description level' in str(e):\n        desc = get_description(obj, level=None)\n    else:\n        raise","preventionTips":["Only pass level for SBWatchpoint objects; pass None for all others.","Check isinstance(object, lldb.SBWatchpoint) before passing a non-None level.","Document which object types support the level parameter in your calling code."],"tags":["lldb","debugger-agent","valueerror","api-mismatch","sbwatchpoint","description"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}