{"record":{"id":"b7a118f7b017fa53","repo":"NationalSecurityAgency/ghidra","slug":"cannot-convert-length-to-length-e","errorCode":null,"errorMessage":"Cannot convert '{length}' to length: {e}","messagePattern":"Cannot convert '(.+?)' to length: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py","lineNumber":694,"sourceCode":"\n\ndef eval_address(address: str) -> Optional[int]:\n    try:\n        return util.parse_and_eval(address)\n    except BaseException as e:\n        if \"can't evaluate expressions when the process is running\" not in str(e):\n            raise RuntimeError(f\"Cannot convert '{address}' to address: {e}\")\n        return None\n\n\ndef eval_range(address: str, length: str) -> Tuple[Optional[int], Optional[int]]:\n    start = eval_address(address)\n    if start is None:\n        return None, None\n    try:\n        end = start + util.parse_and_eval(length)\n    except BaseException as e:\n        raise RuntimeError(f\"Cannot convert '{length}' to length: {e}\")\n    return start, end\n\n\ndef putmem(address: str, length: str, result: lldb.SBCommandReturnObject,\n           pages: bool = True) -> None:\n    start, end = eval_range(address, length)\n    if start is not None and end is not None:\n        put_bytes(start, end, result, pages)\n\n\n@convert_errors\ndef ghidra_trace_putmem(debugger: lldb.SBDebugger, command: str,\n                        result: lldb.SBCommandReturnObject,\n                        internal_dict: Dict[str, Any]) -> None:\n    \"\"\"Record the given block of memory into the Ghidra trace.\n\n    Usage: ghidra trace putmem ADDRESS LENGTH [PAGES]\n","sourceCodeStart":676,"sourceCodeEnd":712,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py#L676-L712","documentation":"Thrown by eval_range() when util.parse_and_eval(length) raises while converting the LENGTH argument into an integer byte count. The original exception is wrapped so the user sees both the offending length token and the underlying LLDB error. This guards the address+length range computation used by putmem, putmem-state, delmem, and get-values-rng.","triggerScenarios":"Calling ghidra trace putmem ADDRESS LENGTH with a LENGTH token that is not a valid LLDB expression (e.g. an empty string, a typo, an undefined symbol, or a register alias LLDB cannot resolve). Also triggered if the inferior is currently running and LLDB refuses to evaluate expressions (SBDebugger.EvaluateExpression fails).","commonSituations":"User typos a length like '0x100z' or passes a label name instead of a numeric size; running the command before stopping the target so LLDB reports 'cannot evaluate expressions when the process is running'; copy-pasting a length from another architecture whose units differ.","solutions":["Stop/halt the target first so LLDB can evaluate the length expression (process must not be running).","Re-type LENGTH as an explicit decimal or hex literal that does not depend on symbol resolution (e.g. 0x40).","If a symbol/size is intended, verify it exists with 'image lookup' or 'expr sizeof(T)' before issuing the command.","Quote the whole command so shlex does not split the length on unexpected whitespace."],"exampleFix":"// before\nghidra trace putmem 0x10000 buffersize\n// after\nghidra trace putmem 0x10000 0x100","handlingStrategy":"validation","validationCode":"# Before calling eval_range-based commands, sanity-check the length token.\nimport shlex\nfrom ghidralldb import util\n\ndef safe_length(length_token: str) -> bool:\n    try:\n        util.parse_and_eval(length_token)\n        return True\n    except BaseException:\n        return False","typeGuard":"def is_evaluatable_length(tok: str) -> bool:\n    # Heuristic: hex/decimal literals always parse; symbols need a stopped target.\n    import re\n    return bool(re.fullmatch(r'(0x[0-9a-fA-F]+|\\d+)', tok)) or tok.isidentifier()","tryCatchPattern":"try:\n    start, end = eval_range(address, length)\nexcept RuntimeError as e:\n    if 'to length' in str(e):\n        # fall back: treat length as a hex literal if possible\n        import re\n        m = re.fullmatch(r'\\s*(0x[0-9a-fA-F]+|\\d+)\\s*', length)\n        if not m:\n            raise\n        start, end = eval_range(address, m.group(1))\n    else:\n        raise","preventionTips":["Always pass LENGTH as an explicit hex or decimal literal rather than a symbol.","Ensure the target is stopped before issuing memory-range commands.","Wrap the whole LLDB command in quotes to avoid shlex splitting the length token."],"tags":["lldb","ghidra-trace","argument-validation","expression-eval"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}