{"record":{"id":"3d5de3defc18673e","repo":"NationalSecurityAgency/ghidra","slug":"invalid-domain-object-id-request-oid-id","errorCode":null,"errorMessage":"Invalid domain object id: {request.oid.id}","messagePattern":"Invalid domain object id: (.+?)","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py","lineNumber":1352,"sourceCode":"        def _handle(reply: bufs.ReplyDisassemble) -> int:\n            return reply.length\n        return self._batch_or_now(root, 'reply_disassemble', _handle)\n\n    def _negotiate(self, description: str) -> str:\n        root = bufs.RootMessage()\n        root.request_negotiate.version = VERSION\n        root.request_negotiate.description = description\n        self._write_methods(root.request_negotiate.methods,\n                            self._method_registry._methods.values())\n\n        def _handle(reply: bufs.ReplyNegotiate) -> str:\n            return reply.description\n        return self._now(root, 'reply_negotiate', _handle)\n\n    def _handle_invoke_method(self, request: bufs.XRequestInvokeMethod) -> Any:\n        if request.HasField('oid'):\n            if request.oid.id not in self._traces:\n                raise KeyError(f\"Invalid domain object id: {request.oid.id}\")\n            trace = self._traces[request.oid.id]\n        else:\n            trace = None\n        name = request.name\n        if not name in self._method_registry._methods:\n            raise KeyError(f\"Invalid method name: {name}\")\n        method = self._method_registry._methods[name]\n        kwargs = self._read_arguments(request.arguments, trace)\n        return method.callback(**kwargs)\n\n\nclass Receiver(Thread):\n    __slots__ = ('client', 'req_queue', '_is_shutdown')\n\n    def __init__(self, client: Client) -> None:\n        super().__init__(daemon=True)\n        self.client: Client = client\n        self.req_queue: deque[RemoteResult[Any, Any]] = deque()","sourceCodeStart":1334,"sourceCodeEnd":1370,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/client.py#L1334-L1370","documentation":"Raised as KeyError by Client._handle_invoke_method() when an incoming invoke-method request references an oid (domain/trace object id) that is not present in the server's self._traces map. The trace was never created, was already closed/removed, or the id is stale.","triggerScenarios":"A client invokes a trace-scoped method after the trace was closed on the server; the client reused a cached oid from a previous connection; the request references an id that was never opened in this session.","commonSituations":"Long-lived client holding stale trace handles across a server restart; race between close and a queued method call; client/server desync after an error.","solutions":["Re-open/refresh the Trace handle on the client before invoking trace-scoped methods after any disconnect or close.","Discard cached oids when the corresponding Trace is closed.","Catch KeyError around invoke and re-establish the trace, then retry once."],"exampleFix":"# before\ntrace.some_method()  # oid no longer valid on server\n# after\ntry:\n    trace.some_method()\nexcept KeyError:\n    trace = client.open_trace(...)\n    trace.some_method()","handlingStrategy":"try-catch","validationCode":"if oid not in client._traces:\n    raise KeyError(f'oid {oid} not open on server')","typeGuard":null,"tryCatchPattern":"try:\n    result = method(...)\nexcept KeyError:\n    trace = reopen_trace()\n    result = method(...)","preventionTips":["Discard cached oids after close/disconnect.","Re-open traces before invoking trace-scoped methods."],"tags":["lifecycle","trace-rmi","method-invocation","state-sync"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}