NationalSecurityAgency/ghidra · error · ValueError

Must have id or path

Error message

Must have id or path

What it means

Raised by Trace.proxy_object() when both id and path are None. proxy_object() builds a TraceObject handle that must reference a node by id, by path, or both; with neither it cannot address anything. This is a precondition violation, not a network/RMI error.

Source

Thrown at Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py:438

            Lifespan, RemoteResult[Any, Lifespan]]:
        return self.client._set_value(self.id, object, span, key, value, schema,
                                      resolution)

    def _retain_values(self, object: TraceObject, span: Lifespan, kinds: str,
                       keys: Iterable[str]) -> Union[
            None, RemoteResult[Any, None]]:
        return self.client._retain_values(self.id, object, span, kinds, keys)

    def proxy_object_id(self, id: int) -> TraceObject:
        return TraceObject.from_id(self, id)

    def proxy_object_path(self, path: str) -> TraceObject:
        return TraceObject.from_path(self, path)

    def proxy_object(self, id: Optional[int] = None,
                     path: Optional[str] = None) -> TraceObject:
        if id is None and path is None:
            raise ValueError("Must have id or path")
        return TraceObject(self, id, path)

    def get_object(self, path_or_id: Union[int, str]) -> TraceObject:
        fut_or_d_obj = self.client._get_object(self.id, path_or_id)
        if isinstance(fut_or_d_obj, DetachedObject):
            return TraceObject(self, fut_or_d_obj.id, fut_or_d_obj.path)

        if isinstance(path_or_id, int):
            fut_path: Future[str] = Future()

            def _done(fut_d_obj: Future[DetachedObject]) -> None:
                fut_path.set_result(fut_d_obj.result().path)

            fut_or_d_obj.add_done_callback(_done)
            return TraceObject(self, path_or_id, fut_path)

        if isinstance(path_or_id, str):
            fut_id: Future[int] = Future()

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Ensure at least one of id or path is a non-None value before calling proxy_object().
  2. Prefer the more specific proxy_object_id(id) or proxy_object_path(path) helpers when you only have one.
  3. Add a guard: if id is None and path is None: raise/return so the failure points at your code, not the library.

Example fix

# before
obj = trace.proxy_object(id=maybe_none, path=maybe_none)
# after
if maybe_id is None and maybe_path is None:
    raise ValueError('Need an id or path to proxy an object')
obj = trace.proxy_object(id=maybe_id, path=maybe_path)
Defensive patterns

Strategy: validation

Validate before calling

if oid is None and opath is None:
    raise ValueError('proxy_object needs an id or a path')

Type guard

def has_id_or_path(i, p) -> bool:
    return i is not None or p is not None

Prevention

When it happens

Trigger: Calling trace.proxy_object() with no arguments, or proxy_object(id=None, path=None) explicitly, or passing variables that both happened to resolve to None (e.g. an object lookup that returned None).

Common situations: Default-None arguments flowing in from a caller that did not yet resolve the node; refactoring that changed a lookup to return None; copy-paste omitting the actual identifier.

Related errors


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