NationalSecurityAgency/ghidra · error · ValueError

Cannot convert ({schema}): '{expr}', value='{val}'

Error message

Cannot convert ({schema}): '{expr}', value='{val}'

What it means

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.

Source

Thrown at Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py:1195

                    return to_string(val, 'utf-32'), sch.STRING
                schema = sch.INT_ARR
            elif schema == sch.CHAR_ARR:
                return to_string(val, 'utf-32'), schema
            return to_int_list(val), schema
        elif (ecode == lldb.eBasicTypeLong or
              ecode == lldb.eBasicTypeUnsignedLong or
              ecode == lldb.eBasicTypeLongLong or
              ecode == lldb.eBasicTypeUnsignedLongLong):
            if schema is not None:
                return to_int_list(val), schema
            else:
                return to_int_list(val), sch.LONG_ARR
    elif type.IsPointerType():
        offset = data_to_int(val.data)
        proc = util.get_process()
        base, addr = STATE.require_trace().extra.require_mm().map(proc, offset)
        return (base, addr), sch.ADDRESS
    raise ValueError(f"Cannot convert ({schema}): '{expr}', value='{val}'")


@convert_errors
def ghidra_trace_set_value(debugger: lldb.SBDebugger, command: str,
                           result: lldb.SBCommandReturnObject,
                           internal_dict: Dict[str, Any]) -> None:
    """Set a value (attribute or element) in the Ghidra trace's object tree.

    Usage: ghidra trace set-value PATH KEY VALUE [SCHEMA]

    The object at PATH must exist, though it need not be inserted, yet. To
    denote an element, KEY must be in the form [INDEX]. VALUE is an expression
    evaluated within the current target. This command will attempt to convert
    the value according to its type, into a type recordable by the Ghidra trace.

    A void or null value implies removal. NOTE: The type of an expression may be
    subject to LLDB's current language. To explicitly specify the type, include
    the SCHEMA argument.

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Pass a primitive-typed expression (int, pointer, bool) or an array of primitives.
  2. If you supplied SCHEMA, ensure it matches the value's actual LLDB basic type.
  3. For structs, set individual primitive members or use putmem on the struct's address instead.
  4. Cast the expression in LLDB to a concrete basic type before recording.

Example fix

// before
ghidra trace set-value Processes[0].Threads[1] attr my_struct
// after
ghidra trace set-value Processes[0].Threads[1] attr (long)my_struct.field
Defensive patterns

Strategy: type-guard

Validate before calling

import lldb

PRIMITIVE_BT = {
    lldb.eBasicTypeBool, lldb.eBasicTypeChar, lldb.eBasicTypeSignedChar,
    lldb.eBasicTypeUnsignedChar, lldb.eBasicTypeWChar, lldb.eBasicTypeSignedWChar,
    lldb.eBasicTypeUnsignedWChar, lldb.eBasicTypeShort, lldb.eBasicTypeUnsignedShort,
    lldb.eBasicTypeInt, lldb.eBasicTypeUnsignedInt, lldb.eBasicTypeLong,
    lldb.eBasicTypeUnsignedLong, lldb.eBasicTypeLongLong,
    lldb.eBasicTypeUnsignedLongLong,
}

def is_recordable_type(value: 'lldb.SBValue') -> bool:
    t = value.type
    return t.IsPointerType() or (t.IsArrayType() and t.GetArrayElementType().GetBasicType() in PRIMITIVE_BT) or (t.GetBasicType() in PRIMITIVE_BT)

Type guard

def eval_value_supported(value: 'lldb.SBValue') -> bool:
    import lldb
    t = value.type
    if t.IsPointerType():
        return True
    bt = t.GetBasicType()
    return bt != lldb.eBasicTypeInvalid and (bt in PRIMITIVE_BT or t.IsArrayType())

Try / catch

try:
    val, schema = eval_value(value, schema)
except ValueError as e:
    if 'Cannot convert' in str(e):
        # fall back: record the object's memory instead of its typed value
        putmem(hex(int(value.addr)), str(value.size), result)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/5eac8bb4acc64e00. Report an issue: GitHub.