{"record":{"id":"5eac8bb4acc64e00","repo":"NationalSecurityAgency/ghidra","slug":"cannot-convert-schema-expr-value-val","errorCode":null,"errorMessage":"Cannot convert ({schema}): '{expr}', value='{val}'","messagePattern":"Cannot convert \\((.+?)\\): '(.+?)', value='(.+?)'","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py","lineNumber":1195,"sourceCode":"                    return to_string(val, 'utf-32'), sch.STRING\n                schema = sch.INT_ARR\n            elif schema == sch.CHAR_ARR:\n                return to_string(val, 'utf-32'), schema\n            return to_int_list(val), schema\n        elif (ecode == lldb.eBasicTypeLong or\n              ecode == lldb.eBasicTypeUnsignedLong or\n              ecode == lldb.eBasicTypeLongLong or\n              ecode == lldb.eBasicTypeUnsignedLongLong):\n            if schema is not None:\n                return to_int_list(val), schema\n            else:\n                return to_int_list(val), sch.LONG_ARR\n    elif type.IsPointerType():\n        offset = data_to_int(val.data)\n        proc = util.get_process()\n        base, addr = STATE.require_trace().extra.require_mm().map(proc, offset)\n        return (base, addr), sch.ADDRESS\n    raise ValueError(f\"Cannot convert ({schema}): '{expr}', value='{val}'\")\n\n\n@convert_errors\ndef ghidra_trace_set_value(debugger: lldb.SBDebugger, command: str,\n                           result: lldb.SBCommandReturnObject,\n                           internal_dict: Dict[str, Any]) -> None:\n    \"\"\"Set a value (attribute or element) in the Ghidra trace's object tree.\n\n    Usage: ghidra trace set-value PATH KEY VALUE [SCHEMA]\n\n    The object at PATH must exist, though it need not be inserted, yet. To\n    denote an element, KEY must be in the form [INDEX]. VALUE is an expression\n    evaluated within the current target. This command will attempt to convert\n    the value according to its type, into a type recordable by the Ghidra trace.\n\n    A void or null value implies removal. NOTE: The type of an expression may be\n    subject to LLDB's current language. To explicitly specify the type, include\n    the SCHEMA argument.","sourceCodeStart":1177,"sourceCodeEnd":1213,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py#L1177-L1213","documentation":"ValueError raised at the bottom of eval_value() when none of the type branches (bool/char/int/long/arrays of those, or pointer) matched the SBValue's type for the requested schema. It is the catch-all 'I do not know how to serialize this value' failure for ghidra trace set-value.","triggerScenarios":"Passing a value whose LLDB type is a struct, union, complex float, vector, or other non-primitive/non-pointer type to set-value. Also when an explicit SCHEMA is given that disagrees with the value's actual type.","commonSituations":"Trying to set-value on a struct field expecting it to be serialized as-is; mismatched SCHEMA argument (e.g. asking for BOOL_ARR on a scalar); referencing a typedef the agent cannot reduce to a basic type.","solutions":["Pass a primitive-typed expression (int, pointer, bool) or an array of primitives.","If you supplied SCHEMA, ensure it matches the value's actual LLDB basic type.","For structs, set individual primitive members or use putmem on the struct's address instead.","Cast the expression in LLDB to a concrete basic type before recording."],"exampleFix":"// before\nghidra trace set-value Processes[0].Threads[1] attr my_struct\n// after\nghidra trace set-value Processes[0].Threads[1] attr (long)my_struct.field","handlingStrategy":"type-guard","validationCode":"import lldb\n\nPRIMITIVE_BT = {\n    lldb.eBasicTypeBool, lldb.eBasicTypeChar, lldb.eBasicTypeSignedChar,\n    lldb.eBasicTypeUnsignedChar, lldb.eBasicTypeWChar, lldb.eBasicTypeSignedWChar,\n    lldb.eBasicTypeUnsignedWChar, lldb.eBasicTypeShort, lldb.eBasicTypeUnsignedShort,\n    lldb.eBasicTypeInt, lldb.eBasicTypeUnsignedInt, lldb.eBasicTypeLong,\n    lldb.eBasicTypeUnsignedLong, lldb.eBasicTypeLongLong,\n    lldb.eBasicTypeUnsignedLongLong,\n}\n\ndef is_recordable_type(value: 'lldb.SBValue') -> bool:\n    t = value.type\n    return t.IsPointerType() or (t.IsArrayType() and t.GetArrayElementType().GetBasicType() in PRIMITIVE_BT) or (t.GetBasicType() in PRIMITIVE_BT)","typeGuard":"def eval_value_supported(value: 'lldb.SBValue') -> bool:\n    import lldb\n    t = value.type\n    if t.IsPointerType():\n        return True\n    bt = t.GetBasicType()\n    return bt != lldb.eBasicTypeInvalid and (bt in PRIMITIVE_BT or t.IsArrayType())","tryCatchPattern":"try:\n    val, schema = eval_value(value, schema)\nexcept ValueError as e:\n    if 'Cannot convert' in str(e):\n        # fall back: record the object's memory instead of its typed value\n        putmem(hex(int(value.addr)), str(value.size), result)\n    else:\n        raise","preventionTips":["Cast struct values to a primitive member or pointer before set-value.","Match the SCHEMA argument to the value's actual basic type.","For aggregates, use putmem on the address rather than set-value."],"tags":["ghidra-trace","type-conversion","set-value","argument-validation"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}