pinpoint-apm/pinpoint · error · IllegalArgumentException
spanEventList is empty.
Error message
spanEventList is empty.
What it means
GrpcSpanProcessorV2.getKeyTime derives the key timestamp for a span's event list by taking the start time of the first SpanEvent. Before doing so it asserts the list is non-empty; if it is empty, it throws IllegalArgumentException because there is no event to derive a timestamp from. This is an internal invariant: the profiler's span compression pipeline expects at least one SpanEvent when computing the key time.
Source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/compress/GrpcSpanProcessorV2.java:128
pSpanEvent.setDepth(depth);
} else {
int currentDepth = spanEvent.getDepth();
if (currentDepth == prevDepth) {
// skip
pSpanEvent.setDepth(0);
} else {
pSpanEvent.setDepth(currentDepth);
}
prevDepth = currentDepth;
}
}
}
private long getKeyTime(List<SpanEvent> spanEventList) {
if (CollectionUtils.isEmpty(spanEventList)) {
throw new IllegalArgumentException("spanEventList is empty.");
}
final SpanEvent first = spanEventList.get(0);
if (first == null) {
throw new IllegalStateException("first SpanEvent is null");
}
return first.getStartTime();
}
}
View on GitHub (pinned to 744c3d3075)
Solutions
- Check why the Span reaching GrpcSpanProcessorV2 has an empty spanEventList; ensure at least one SpanEvent is added before the span is completed/flushed.
- Guard in calling code: if span.getSpanEventList() is empty, skip key-time computation or use the span's own start time.
- Upgrade Pinpoint agent — newer versions tolerate empty event lists in the compression pipeline.
- If a custom plugin/filter strips SpanEvents, fix the plugin to preserve at least the root event.
Example fix
// before
long keyTime = grpcSpanProcessor.keyTime(span.getSpanEventList());
// after
List<SpanEvent> events = span.getSpanEventList();
long keyTime = (events != null && !events.isEmpty())
? events.get(0).getStartTime()
: span.getStartTime(); Defensive patterns
Strategy: validation
Validate before calling
if (spanEventList == null || spanEventList.isEmpty()) {
// skip key-time computation or fall back to span start time
return span.getStartTime();
} Try / catch
try {
long keyTime = processor.keyTime(span.getSpanEventList());
} catch (IllegalArgumentException e) {
logger.warn("Span {} has empty event list; using span start time", span.getSpanId(), e);
keyTime = span.getStartTime();
} Prevention
- Never complete/flush a span before at least one SpanEvent is recorded, or accept spans with empty event lists downstream.
- Audit custom plugins/interceptors that might remove all SpanEvents.
- Add a pre-serialization assertion that event lists are non-empty in trace tests.
When it happens
Trigger: Calling keyTime() (via GrpcSpanProcessorV2 span processing during gRPC span serialization) with a List<SpanEvent> that has zero elements — e.g. a Span with no span events recorded before the span is flushed to the collector.
Common situations: Spans completed without any child events (async spans, filtered-out events, or tracing plugins that produce empty event lists); custom interceptors that remove or never add SpanEvents; races where events are cleared before the span is sent.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- first SpanEvent is null
- list size not same
- Unexpected TraceId type: ${traceId}
- UNSUPPORTED_OPERATION
- startTime not recorded
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/821d693d5b9d11d4.
Report an issue: GitHub.