{"record":{"id":"d12da5f78a8a4c79","repo":"NationalSecurityAgency/ghidra","slug":"all-traceobject-parameters-must-come-from-the-same","errorCode":null,"errorMessage":"All TraceObject parameters must come from the same trace","messagePattern":"All TraceObject parameters must come from the same trace","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/RemoteMethod.java","lineNumber":178,"sourceCode":"\tdefault Trace validate(Map<String, Object> arguments) {\n\t\tTrace trace = null;\n\t\tSchemaContext ctx = PrimitiveTraceObjectSchema.MinimalSchemaContext.INSTANCE;\n\t\tfor (Map.Entry<String, RemoteParameter> ent : parameters().entrySet()) {\n\t\t\tif (!arguments.containsKey(ent.getKey())) {\n\t\t\t\tif (ent.getValue().required()) {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"Missing required parameter '\" + ent.getKey() + \"'\");\n\t\t\t\t}\n\t\t\t\tcontinue; // Should not need to check the default value\n\t\t\t}\n\t\t\tObject arg = arguments.get(ent.getKey());\n\t\t\tif (arg instanceof TraceObject obj) {\n\t\t\t\tif (trace == null) {\n\t\t\t\t\ttrace = obj.getTrace();\n\t\t\t\t\tctx = trace.getObjectManager().getRootSchema().getContext();\n\t\t\t\t}\n\t\t\t\telse if (trace != obj.getTrace()) {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"All TraceObject parameters must come from the same trace\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tSchemaName schName = ent.getValue().type();\n\t\t\tTraceObjectSchema sch = ctx.getSchemaOrNull(schName);\n\t\t\tcheckType(ent.getKey(), schName, sch, arg);\n\t\t}\n\t\tfor (Map.Entry<String, Object> ent : arguments.entrySet()) {\n\t\t\tif (!parameters().containsKey(ent.getKey())) {\n\t\t\t\tthrow new IllegalArgumentException(\"Extra argument '\" + ent.getKey() + \"'\");\n\t\t\t}\n\t\t}\n\t\treturn trace;\n\t}\n\n\t/**\n\t * Invoke the remote method, getting a future result.\n\t * ","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/api/tracermi/RemoteMethod.java#L160-L196","documentation":"Thrown by RemoteMethod.validate() when two or more TraceObject arguments originate from different Trace instances. The method tracks the first TraceObject's trace and rejects any subsequent TraceObject whose getTrace() differs.","triggerScenarios":"Calling validate() with an argument map containing at least two TraceObject values whose getTrace() returns non-equal traces.","commonSituations":"Mixing objects from an old trace and a newly opened trace; passing a breakpoint object from one trace and a process object from another; stale references after a target restart created a new trace.","solutions":["Ensure all TraceObject arguments come from the same trace; re-fetch objects from the current trace.","Before validate(), assert that all TraceObject args share obj.getTrace().","Close/discard references to the old trace after switching to a new one."],"exampleFix":"// before\nmethod.validate(Map.of(\"a\", objFromTrace1, \"b\", objFromTrace2));\n\n// after\nTrace current = requireCurrentTrace();\nTraceObject a = current.getObjectManager().getObjectByPath(\"a\");\nTraceObject b = current.getObjectManager().getObjectByPath(\"b\");\nmethod.validate(Map.of(\"a\", a, \"b\", b));","handlingStrategy":"validation","validationCode":"// Ensure all TraceObject args share one trace:\nTrace expected = null;\nfor (Object v : arguments.values()) {\n    if (v instanceof TraceObject o) {\n        if (expected == null) expected = o.getTrace();\n        else if (expected != o.getTrace())\n            throw new IllegalStateException(\"Mixed traces in arguments\");\n    }\n}","typeGuard":"static boolean allObjectsSameTrace(Map<String,Object> args) {\n    Trace t = null;\n    for (Object v : args.values()) {\n        if (v instanceof TraceObject o) {\n            if (t == null) t = o.getTrace();\n            else if (t != o.getTrace()) return false;\n        }\n    }\n    return true;\n}","tryCatchPattern":"try {\n    method.validate(arguments);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"same trace\")) {\n        // refresh all objects from the current trace and retry\n    } else throw e;\n}","preventionTips":["Re-fetch TraceObjects from the current trace right before invoking.","Discard object references from prior traces after a target switch."],"tags":["tracermi","remote-method","trace-object","multi-trace","debugger"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}