pinpoint-apm/pinpoint · error · IllegalStateException
first SpanEvent is null
Error message
first SpanEvent is null
What it means
After confirming the spanEventList is non-empty, getKeyTime asserts that the first element is not null and throws IllegalStateException if it is. The list is expected to contain real SpanEvent objects; a null first element means the internal event list was populated with a null entry, violating the profiler's invariants.
Source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/compress/GrpcSpanProcessorV2.java:132
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
- Find and fix code that adds null SpanEvents to the event list before span serialization.
- Filter nulls before passing the list: events.removeIf(Objects::isNull) or use a non-null-allowing collection during trace recording.
- Check for concurrent modification of the span event list (race between event add/clear and flush).
- If reproducible, capture the trace and report to Pinpoint with the plugin/interceptor in use.
Example fix
// before List<SpanEvent> events = span.getSpanEventList(); long keyTime = grpcSpanProcessor.keyTime(events); // after List<SpanEvent> events = span.getSpanEventList(); events.removeIf(Objects::isNull); long keyTime = events.isEmpty() ? span.getStartTime() : events.get(0).getStartTime();
Defensive patterns
Strategy: validation
Validate before calling
if (spanEventList != null && !spanEventList.isEmpty() && spanEventList.get(0) == null) {
spanEventList.removeIf(Objects::isNull); // sanitize before key-time computation
} Try / catch
try {
long keyTime = processor.keyTime(span.getSpanEventList());
} catch (IllegalStateException e) {
logger.warn("Null SpanEvent in list for span {}", span.getSpanId(), e);
keyTime = span.getStartTime();
} Prevention
- Enforce non-null SpanEvents wherever events are added to the trace (Objects.requireNonNull).
- Avoid manual list manipulation/reflection on internal event lists.
- Synchronize access to span event lists if traces can be modified concurrently.
When it happens
Trigger: Calling keyTime() with a List<SpanEvent> whose element at index 0 is null — e.g. code that added null to the event list, or a list implementation that pads/truncates leaving nulls.
Common situations: Custom instrumentation or plugins inserting null SpanEvents into the trace context; reflection/manual list manipulation; corrupted trace state after concurrent modification of the event list.
Related errors
- spanEventList is empty.
- 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/6f6b4fcc96af20e1.
Report an issue: GitHub.