NationalSecurityAgency/ghidra · error · ValueError

Value '{address}' does not evaluate to an int

Error message

Value '{address}' does not evaluate to an int

What it means

Raised by eval_range() (commands.py:559-560) when parse_and_eval(length) succeeded but returned a non-int (e.g. a string, float, or None). The length resolved to a value but not to an integer usable as a byte count. Note the f-string uses {address} (likely a copy-paste bug) so the message names the address rather than the offending length.

Source

Thrown at Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py:560

def eval_address(address: Union[str, int]) -> int:
    try:
        result = util.parse_and_eval(address)
        if isinstance(result, int):
            return result
        raise ValueError(f"Value '{address}' does not evaluate to an int")
    except Exception:
        raise RuntimeError(f"Cannot convert '{address}' to address")


def eval_range(address: Union[str, int],
               length: Union[str, int]) -> Tuple[int, int]:
    start = eval_address(address)
    try:
        l = util.parse_and_eval(length)
    except Exception as e:
        raise RuntimeError(f"Cannot convert '{length}' to length")
    if not isinstance(l, int):
        raise ValueError(f"Value '{address}' does not evaluate to an int")
    end = start + l
    return start, end


def putmem(address: Union[str, int], length: Union[str, int],
           pages: bool = True, display_result: bool = True) -> Dict[str, int]:
    start, end = eval_range(address, length)
    return put_bytes(start, end, pages, display_result)


def ghidra_trace_putmem(address: Union[str, int], length: Union[str, int],
                        pages: bool = True) -> Dict[str, int]:
    """Record the given block of memory into the Ghidra trace."""

    STATE.require_tx()
    return putmem(address, length, pages, True)

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Coerce or pass length as a plain int literal (e.g. 0x100) rather than a typed expression.
  2. If a typed value is unavoidable, pre-convert: int(util.parse_and_eval(length)) inside a try, then pass the int.
  3. Report the upstream evaluator quirk if it persists — the message names address but the culprit is the length operand.

Example fix

// before
ghidra_trace_putmem(addr, 'some_typed_expr')   # non-int result

// after
length = util.parse_and_eval('some_typed_expr')
if not isinstance(length, int):
    length = int(length)
ghidra_trace_putmem(addr, length)
Defensive patterns

Strategy: type-guard

Validate before calling

def coerce_length(expr):
    val = util.parse_and_eval(expr)
    if not isinstance(val, int):
        val = int(val)
    return val

length = coerce_length(length_expr)
ghidra_trace_putmem(address, length)

Type guard

def length_is_int(expr) -> bool:
    try:
        return isinstance(util.parse_and_eval(expr), int)
    except Exception:
        return False

Try / catch

try:
    ghidra_trace_putmem(address, length)
except (RuntimeError, ValueError) as e:
    if 'does not evaluate to an int' in str(e):
        length = int(util.parse_and_eval(length))
        ghidra_trace_putmem(address, length)
    else:
        raise

Prevention

When it happens

Trigger: parse_and_eval returning a type other than int for the length argument; passing a length expression that evaluates to a string or float; some dbgeng evaluators returning variant types for certain expressions.

Common situations: Length expression that resolves to a symbol value with type metadata instead of a raw number; evaluator returning a Python wrapper object that fails isinstance(int); edge cases in pybag/dbgmodel bridging.

Related errors


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