{"record":{"id":"7f76bb2757fa049c","repo":"NationalSecurityAgency/ghidra","slug":"cannot-convert-s-value-type","errorCode":null,"errorMessage":"Cannot convert {}'s value: '{}', type: '{}'","messagePattern":"Cannot convert (.+?)'s value: '(.+?)', type: '(.+?)'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/arch.py","lineNumber":249,"sourceCode":"    return memory_mappers[lang]\n\n\nclass DefaultRegisterMapper(object):\n\n    def __init__(self, byte_order: str) -> None:\n        if not byte_order in ['big', 'little']:\n            raise ValueError(\"Invalid byte_order: {}\".format(byte_order))\n        self.byte_order = byte_order\n\n    def map_name(self, proc: int, name: str):\n        return name\n\n    def map_value(self, proc: int, name: str, value: int):\n        try:\n            # TODO: this seems half-baked\n            av = value.to_bytes(8, \"big\")\n        except Exception:\n            raise ValueError(\"Cannot convert {}'s value: '{}', type: '{}'\"\n                             .format(name, value, type(value)))\n        return RegVal(self.map_name(proc, name), av)\n\n    def map_name_back(self, proc: int, name: str) -> str:\n        return name\n\n    def map_value_back(self, proc: int, name: str, value: bytes):\n        return RegVal(self.map_name_back(proc, name), value)\n\n\nclass Intel_x86_64_RegisterMapper(DefaultRegisterMapper):\n\n    def __init__(self):\n        super().__init__('little')\n\n    def map_name(self, proc, name):\n        if name is None:\n            return 'UNKNOWN'","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/arch.py#L231-L267","documentation":"Thrown by DefaultRegisterMapper.map_value() when converting a register value to an 8-byte big-endian representation fails. The method calls value.to_bytes(8, 'big'), and if the value is not an integer or doesn't fit in 8 bytes, the exception is caught and re-raised as ValueError with the register name, value, and type. This indicates the register value from the debugger is in an unexpected format.","triggerScenarios":"map_value(proc, name, value) calls value.to_bytes(8, 'big'). This fails if value is not an int (e.g., it's a float, string, or None), or if the int is negative, or if it exceeds 8 bytes (larger than 2^64-1). The generic except clause wraps the original exception into a ValueError with diagnostic info.","commonSituations":"The debugger returns a register value as a string or bytearray instead of an int. A 128-bit register (e.g., AVX/SSE) value exceeds the 8-byte limit. A negative value is returned where unsigned is expected. The dbgeng bridge returns register values in a format the mapper doesn't expect.","solutions":["Check the type and magnitude of the value before calling map_value — convert to a non-negative int first.","If the register is wider than 64 bits, subclass DefaultRegisterMapper and handle larger sizes.","Fix the upstream code that provides register values to ensure they're ints in [0, 2^64).","Add explicit type conversion: int(value) with appropriate bounds checking."],"exampleFix":"# Before:\n# mapper.map_value(proc, name, raw_value)  # raw_value may be str or negative\n#\n# After:\n# val = int(raw_value) if not isinstance(raw_value, int) else raw_value\n# val = val & 0xFFFFFFFFFFFFFFFF  # mask to unsigned 64-bit\n# mapper.map_value(proc, name, val)","handlingStrategy":"validation","validationCode":"# Before calling map_value, ensure value is a non-negative int fitting in 8 bytes:\nif isinstance(value, int) and 0 <= value < (1 << 64):\n    result = mapper.map_value(proc, name, value)\nelse:\n    value = int(value) & 0xFFFFFFFFFFFFFFFF\n    result = mapper.map_value(proc, name, value)","typeGuard":"def is_valid_register_value(value) -> bool:\n    return isinstance(value, int) and 0 <= value < (1 << 64)","tryCatchPattern":"try:\n    result = mapper.map_value(proc, name, value)\nexcept ValueError as e:\n    if 'Cannot convert' in str(e):\n        # coerce to int and mask, then retry\n        value = int(value) & 0xFFFFFFFFFFFFFFFF\n        result = mapper.map_value(proc, name, value)\n    else:\n        raise","preventionTips":["Always convert register values to non-negative ints before calling map_value.","Mask values to the register width to avoid overflow in to_bytes().","Handle wider-than-64-bit registers with a custom mapper subclass.","Validate the debugger's register value format at the bridge layer."],"tags":["debugger-agent","register-mapping","type-conversion","python","dbgeng"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}