NationalSecurityAgency/ghidra · error · TraceRmiError
snap or time required
Error message
snap or time required
What it means
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.
Source
Thrown at Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiHandler.java:1187
OpenTrace open = requireOpenTrace(req.getOid());
Object objVal = open.toValue(value.getValue());
TraceObject object = open.getObject(value.getParent(), objVal != null);
if (object == null) {
// Implies request was to set value to null
return ReplySetValue.newBuilder().setSpan(makeSpan(Lifespan.EMPTY)).build();
}
TraceObjectValue val = object.setValue(toLifespan(value.getSpan()), value.getKey(), objVal,
toResolution(req.getResolution()));
return ReplySetValue.newBuilder()
.setSpan(makeSpan(val == null ? Lifespan.EMPTY : val.getLifespan()))
.build();
}
protected ReplySnapshot handleSnapshot(RequestSnapshot req) {
OpenTrace open = requireOpenTrace(req.getOid());
TraceSnapshot snapshot = switch (req.getTimeCase()) {
case TIME_NOT_SET -> throw new TraceRmiError("snap or time required");
case SNAP -> open.createSnapshot(req.getSnap().getSnap());
case SCHEDULE -> open.createSnapshot(
TraceSchedule.parse(req.getSchedule().getSchedule(), TimeRadix.DEC));
};
snapshot.setDescription(req.getDescription());
if (!"".equals(req.getDatetime())) {
Instant instant =
DateTimeFormatter.ISO_INSTANT.parse(req.getDatetime()).query(Instant::from);
snapshot.setRealTime(instant.toEpochMilli());
}
return ReplySnapshot.newBuilder()
.setSnap(Snap.newBuilder().setSnap(snapshot.getKey()))
.build();
}
protected ReplyStartTx handleStartTx(RequestStartTx req) {
OpenTrace open = requireOpenTrace(req.getOid());
Tid tid = requireAvailableTid(open, req.getTxid());View on GitHub (pinned to d5f144c24d)
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.
Example fix
// before
RequestSnapshot req = RequestSnapshot.newBuilder().setOid(oid).build();
// after
RequestSnapshot req = RequestSnapshot.newBuilder()
.setOid(oid)
.setSnap(Snap.newBuilder().setSnap(currentSnap))
.build(); Defensive patterns
Strategy: validation
Validate before calling
if (req.getTimeCase() == RequestSnapshot.TimeCase.TIME_NOT_SET) {
throw new IllegalArgumentException("snapshot requires snap or schedule");
} Type guard
boolean hasTime(RequestSnapshot req) {
return req.getTimeCase() != RequestSnapshot.TimeCase.TIME_NOT_SET;
} Try / catch
try {
handler.snapshot(req);
} catch (TraceRmiError e) {
// no time set; set snap or schedule and retry
} Prevention
- 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.
When it happens
Trigger: The client builds a RequestSnapshot without calling setSnap or setSchedule, leaving the time oneof unset.
Common situations: 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.
Related errors
- Usage: ghidra trace new-snap [SNAP] DESCRIPTION
- No saved offers to launch {}
- Range [%s:%x+%x] entirely exceeds space min
- Trace is not from this connection
- CreateTrace: path (name) cannot be empty
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/dec9d956dd8831e5.
Report an issue: GitHub.