NationalSecurityAgency/ghidra · error · ValueError
Cannot convert: {value:r}
Error message
Cannot convert: {value:r} What it means
Raised by Trace._fix_value() when a value tagged with schema OBJECT is neither a DetachedObject nor a TraceObject. _fix_value() coerces wire objects into TraceObject handles; only those two types are acceptable for an OBJECT schema, so any other type is an internal contract violation. End users normally should not see this — it implies the schema/value pairing is inconsistent.
Source
Thrown at Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py:472
if isinstance(path_or_id, str):
fut_id: Future[int] = Future()
def _done(fut_d_obj: Future[DetachedObject]) -> None:
fut_id.set_result(fut_d_obj.result().id)
fut_or_d_obj.add_done_callback(_done)
return TraceObject(self, fut_id, path_or_id)
def _fix_value(self, value: Any, schema: sch.Schema) -> Any:
if schema != sch.OBJECT:
return value
elif isinstance(value, DetachedObject):
return TraceObject(self, value.id, value.path)
elif isinstance(value, TraceObject):
return value
else:
raise ValueError(f"Cannot convert: {value:r}")
def _make_values(self, values: Iterable[Tuple[
DetachedObject, Lifespan, str, Tuple[Any, sch.Schema]
]]) -> List[TraceObjectValue]:
return [
TraceObjectValue(TraceObject(self, d_obj.id, d_obj.path),
span, key, self._fix_value(value, schema), schema)
for d_obj, span, key, (value, schema) in values
]
def _convert_values(self, results: Union[
List[Tuple[DetachedObject, Lifespan, str, Tuple[Any, sch.Schema]]],
Future[List[
Tuple[DetachedObject, Lifespan, str, Tuple[Any, sch.Schema]]]]]):
if isinstance(results, List):
return self._make_values(results)
fut_values: Future[List[TraceObjectValue]] = Future()View on GitHub (pinned to d5f144c24d)
Solutions
- Ensure OBJECT-typed values are always produced via trace.proxy_object()/from_id/from_path so they are TraceObject instances.
- Verify the client and server run compatible ghidratrace versions (see negotiate/version).
- If writing custom method glue, double-check the declared schema matches the actual returned type.
Example fix
// before (server-side method returning a raw id for an OBJECT schema) return raw_id // after return trace.proxy_object(id=raw_id)
Defensive patterns
Strategy: type-guard
Validate before calling
from ghidratrace.client import TraceObject, DetachedObject
if schema == sch.OBJECT and not isinstance(value, (TraceObject, DetachedObject)):
raise TypeError('OBJECT value must be a TraceObject/DetachedObject') Type guard
def is_object_value(v) -> bool:
from ghidratrace.client import TraceObject, DetachedObject
return isinstance(v, (TraceObject, DetachedObject)) Prevention
- Produce OBJECT values only via proxy_object/from_id/from_path.
- Keep client and server on the same ghidratrace version.
When it happens
Trigger: An OBJECT-typed method return or element arriving as a raw dict, int, or str; a custom schema or method registration that declared sch.OBJECT but returned an incompatible Python object; mismatched ghidratrace versions between client and server.
Common situations: Version skew between the Python trace client and the Ghidra backend; a plugin that hand-constructs values instead of using proxy_object; corruption/partial deserialization.
Related errors
- Cannot write Value: {schema}, {value}, {type(value)}
- The parameter '%s' of method '%s' refers to a non-existent s
- Cannot get schema for {annotation}
- Object/proxy has neither id nor path!: {}
- Could not read value: {}
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/2c42a16dc5145845.
Report an issue: GitHub.