{"record":{"id":"dec9d956dd8831e5","repo":"NationalSecurityAgency/ghidra","slug":"snap-or-time-required","errorCode":null,"errorMessage":"snap or time required","messagePattern":"snap or time required","errorType":"exception","errorClass":"TraceRmiError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiHandler.java","lineNumber":1187,"sourceCode":"\t\tOpenTrace open = requireOpenTrace(req.getOid());\n\t\tObject objVal = open.toValue(value.getValue());\n\t\tTraceObject object = open.getObject(value.getParent(), objVal != null);\n\t\tif (object == null) {\n\t\t\t// Implies request was to set value to null\n\t\t\treturn ReplySetValue.newBuilder().setSpan(makeSpan(Lifespan.EMPTY)).build();\n\t\t}\n\n\t\tTraceObjectValue val = object.setValue(toLifespan(value.getSpan()), value.getKey(), objVal,\n\t\t\ttoResolution(req.getResolution()));\n\t\treturn ReplySetValue.newBuilder()\n\t\t\t\t.setSpan(makeSpan(val == null ? Lifespan.EMPTY : val.getLifespan()))\n\t\t\t\t.build();\n\t}\n\n\tprotected ReplySnapshot handleSnapshot(RequestSnapshot req) {\n\t\tOpenTrace open = requireOpenTrace(req.getOid());\n\t\tTraceSnapshot snapshot = switch (req.getTimeCase()) {\n\t\t\tcase TIME_NOT_SET -> throw new TraceRmiError(\"snap or time required\");\n\t\t\tcase SNAP -> open.createSnapshot(req.getSnap().getSnap());\n\t\t\tcase SCHEDULE -> open.createSnapshot(\n\t\t\t\tTraceSchedule.parse(req.getSchedule().getSchedule(), TimeRadix.DEC));\n\t\t};\n\t\tsnapshot.setDescription(req.getDescription());\n\t\tif (!\"\".equals(req.getDatetime())) {\n\t\t\tInstant instant =\n\t\t\t\tDateTimeFormatter.ISO_INSTANT.parse(req.getDatetime()).query(Instant::from);\n\t\t\tsnapshot.setRealTime(instant.toEpochMilli());\n\t\t}\n\t\treturn ReplySnapshot.newBuilder()\n\t\t\t\t.setSnap(Snap.newBuilder().setSnap(snapshot.getKey()))\n\t\t\t\t.build();\n\t}\n\n\tprotected ReplyStartTx handleStartTx(RequestStartTx req) {\n\t\tOpenTrace open = requireOpenTrace(req.getOid());\n\t\tTid tid = requireAvailableTid(open, req.getTxid());","sourceCodeStart":1169,"sourceCodeEnd":1205,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiHandler.java#L1169-L1205","documentation":"Thrown by TraceRmiHandler.handleSnapshot when the RequestSnapshot's time case is TIME_NOT_SET — neither a snap number nor a schedule string was supplied. Creating a snapshot requires a time anchor, so the request is rejected with TraceRmiError.","triggerScenarios":"The client builds a RequestSnapshot without calling setSnap or setSchedule, leaving the time oneof unset.","commonSituations":"Client omits the time field assuming a default; code path that constructs the request conditionally skips both branches; schema confusion about which field is required.","solutions":["Always set exactly one of setSnap (numeric snapshot) or setSchedule (a TraceSchedule string) on RequestSnapshot.","If you want 'current', explicitly pass the current snap number rather than leaving it unset.","Validate the request's getTimeCase() != TIME_NOT_SET before sending."],"exampleFix":"// before\nRequestSnapshot req = RequestSnapshot.newBuilder().setOid(oid).build();\n\n// after\nRequestSnapshot req = RequestSnapshot.newBuilder()\n    .setOid(oid)\n    .setSnap(Snap.newBuilder().setSnap(currentSnap))\n    .build();","handlingStrategy":"validation","validationCode":"if (req.getTimeCase() == RequestSnapshot.TimeCase.TIME_NOT_SET) {\n    throw new IllegalArgumentException(\"snapshot requires snap or schedule\");\n}","typeGuard":"boolean hasTime(RequestSnapshot req) {\n    return req.getTimeCase() != RequestSnapshot.TimeCase.TIME_NOT_SET;\n}","tryCatchPattern":"try {\n    handler.snapshot(req);\n} catch (TraceRmiError e) {\n    // no time set; set snap or schedule and retry\n}","preventionTips":["Always set either setSnap or setSchedule on RequestSnapshot.","Pass the current snap explicitly rather than relying on a default.","Unit-test request builders to ensure the time oneof is populated."],"tags":["trace-rmi","snapshot","validation","time"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}