pinpoint-apm/pinpoint · error · IllegalStateException

list size not same

Error message

list size not same

What it means

GrpcSpanProcessorV2 converts a trace's SpanEvent list into protobuf PSpanEvent.Builder list, keeping both lists index-aligned so depth/sequence can be written in a single post-processing pass. postProcess() enforces the invariant that the input and output lists have the same size and throws IllegalStateException("list size not same") when they diverge, because alignment-based compression would otherwise corrupt span data. This is a hard internal consistency check, not user input validation.

Source

Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/compress/GrpcSpanProcessorV2.java:88

        pSpanChunk.setKeyTime(keyTime);
        postProcess(keyTime, spanEventList, tSpanEventList);
    }

    @Override
    public void postProcess(Span span, PSpan.Builder pSpan) {
        final List<SpanEvent> spanEventList = span.getSpanEventList();
        final List<PSpanEvent.Builder> tSpanEventList = pSpan.getSpanEventBuilderList();
        long keyTime = span.getStartTime();
        postProcess(keyTime, spanEventList, tSpanEventList);
    }

    private void postProcess(long keyTime, List<SpanEvent> spanEventList, List<PSpanEvent.Builder> pSpanEventList) {
        final int spanEventSize = CollectionUtils.nullSafeSize(spanEventList);
        if (spanEventSize == 0) {
            return;
        }
        if (!(spanEventSize == CollectionUtils.nullSafeSize(pSpanEventList))) {
            throw new IllegalStateException("list size not same");
        }
        // check list type
        assert spanEventList instanceof RandomAccess;

        int prevDepth = 0;
        boolean first = true;

        final int listSize = spanEventList.size();
        for (int i = 0; i < listSize; i++) {
            final SpanEvent spanEvent = spanEventList.get(i);
            final PSpanEvent.Builder pSpanEvent = pSpanEventList.get(i);

            final long startTime = spanEvent.getStartTime();
            final long startElapsedTime = startTime - keyTime;
            pSpanEvent.setStartElapsed((int) startElapsedTime);
            keyTime = startTime;

            if (first) {

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Audit the code that builds pSpanEventList from spanEventList to ensure every retained SpanEvent yields exactly one builder (filter both lists together).
  2. Fix or remove custom SpanEventFilter implementations that exclude events after the builder list was created.
  3. Ensure spanPostProcess is called with the same list instances that were used during spanEvent building, not copies.
  4. Reproduce with a large/recursive span chunk and log both sizes to identify which events are dropped.
  5. Upgrade the Pinpoint agent if the mismatch is caused by a known bug in the V2 processor.

Example fix

// before
List<PSpanEvent.Builder> builders = events.stream()
    .filter(e -> e.isFiltered())   // only filters one side?
    .map(this::toBuilder).collect(toList());
processor.spanPostProcess(eventList, builders); // sizes differ -> IllegalStateException
// after
List<PSpanEvent.Builder> builders = new ArrayList<>(eventList.size());
for (SpanEvent e : eventList) {
    if (e.isFiltered()) {
        builders.add(toBuilder(e));
    }
}
List<SpanEvent> kept = filterEvents(eventList); // filter the source list identically
processor.spanPostProcess(kept, builders); // sizes guaranteed equal
Defensive patterns

Strategy: try-catch

Validate before calling

if (CollectionUtils.nullSafeSize(spanEventList) != CollectionUtils.nullSafeSize(pSpanEventList)) {
    throw new AssertionError("converter dropped events: "
        + CollectionUtils.nullSafeSize(spanEventList) + " vs "
        + CollectionUtils.nullSafeSize(pSpanEventList));
} // run before invoking the processor to fail fast with context

Type guard

boolean isAligned(List<?> a, List<?> b) {
    return CollectionUtils.nullSafeSize(a) == CollectionUtils.nullSafeSize(b);
}

Try / catch

try {
    spanPostProcess(spanEventList, pSpanEventList);
} catch (IllegalStateException e) {
    logger.error("Span event list misaligned: {} vs {}",
        spanEventList.size(), pSpanEventList.size(), e);
}

Prevention

When it happens

Trigger: Calling postProcess (via spanPostProcess) when the filtered spanEventList and the built pSpanEventList have different lengths — e.g. some SpanEvents were skipped during filtering/builder creation while the source list still contains them, or events were appended to only one of the two lists.

Common situations: Bugs in custom SpanEvent filters or span event converters that drop events on one side; modifications to the span-event list between buildSpanChunk/buildSpan and postProcess; agent version mismatches where processor V2 invariants are violated by newer/older event structures; corrupted trace state from earlier lifecycle errors.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/b4532ae88021588c. Report an issue: GitHub.