{"record":{"id":"51e80e6edf74ca15","repo":"NationalSecurityAgency/ghidra","slug":"must-have-id-or-path","errorCode":null,"errorMessage":"Must have id or path","messagePattern":"Must have id or path","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py","lineNumber":438,"sourceCode":"            Lifespan, RemoteResult[Any, Lifespan]]:\n        return self.client._set_value(self.id, object, span, key, value, schema,\n                                      resolution)\n\n    def _retain_values(self, object: TraceObject, span: Lifespan, kinds: str,\n                       keys: Iterable[str]) -> Union[\n            None, RemoteResult[Any, None]]:\n        return self.client._retain_values(self.id, object, span, kinds, keys)\n\n    def proxy_object_id(self, id: int) -> TraceObject:\n        return TraceObject.from_id(self, id)\n\n    def proxy_object_path(self, path: str) -> TraceObject:\n        return TraceObject.from_path(self, path)\n\n    def proxy_object(self, id: Optional[int] = None,\n                     path: Optional[str] = None) -> TraceObject:\n        if id is None and path is None:\n            raise ValueError(\"Must have id or path\")\n        return TraceObject(self, id, path)\n\n    def get_object(self, path_or_id: Union[int, str]) -> TraceObject:\n        fut_or_d_obj = self.client._get_object(self.id, path_or_id)\n        if isinstance(fut_or_d_obj, DetachedObject):\n            return TraceObject(self, fut_or_d_obj.id, fut_or_d_obj.path)\n\n        if isinstance(path_or_id, int):\n            fut_path: Future[str] = Future()\n\n            def _done(fut_d_obj: Future[DetachedObject]) -> None:\n                fut_path.set_result(fut_d_obj.result().path)\n\n            fut_or_d_obj.add_done_callback(_done)\n            return TraceObject(self, path_or_id, fut_path)\n\n        if isinstance(path_or_id, str):\n            fut_id: Future[int] = Future()","sourceCodeStart":420,"sourceCodeEnd":456,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py#L420-L456","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Ensure at least one of id or path is a non-None value before calling proxy_object().","Prefer the more specific proxy_object_id(id) or proxy_object_path(path) helpers when you only have one.","Add a guard: if id is None and path is None: raise/return so the failure points at your code, not the library."],"exampleFix":"# before\nobj = trace.proxy_object(id=maybe_none, path=maybe_none)\n# after\nif maybe_id is None and maybe_path is None:\n    raise ValueError('Need an id or path to proxy an object')\nobj = trace.proxy_object(id=maybe_id, path=maybe_path)","handlingStrategy":"validation","validationCode":"if oid is None and opath is None:\n    raise ValueError('proxy_object needs an id or a path')","typeGuard":"def has_id_or_path(i, p) -> bool:\n    return i is not None or p is not None","tryCatchPattern":null,"preventionTips":["Use proxy_object_id/proxy_object_path when you have only one identifier.","Resolve None lookups before proxying."],"tags":["validation","trace-rmi","object-model"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}