{"record":{"id":"6f6b4fcc96af20e1","repo":"pinpoint-apm/pinpoint","slug":"first-spanevent-is-null","errorCode":null,"errorMessage":"first SpanEvent is null","messagePattern":"first SpanEvent is null","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/compress/GrpcSpanProcessorV2.java","lineNumber":132,"sourceCode":"                if (currentDepth == prevDepth) {\n                    // skip\n                    pSpanEvent.setDepth(0);\n                } else {\n                    pSpanEvent.setDepth(currentDepth);\n                }\n                prevDepth = currentDepth;\n            }\n        }\n    }\n\n\n    private long getKeyTime(List<SpanEvent> spanEventList) {\n        if (CollectionUtils.isEmpty(spanEventList)) {\n            throw new IllegalArgumentException(\"spanEventList is empty.\");\n        }\n        final SpanEvent first = spanEventList.get(0);\n        if (first == null) {\n            throw new IllegalStateException(\"first SpanEvent is null\");\n        }\n\n        return first.getStartTime();\n    }\n\n}\n","sourceCodeStart":114,"sourceCodeEnd":139,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/compress/GrpcSpanProcessorV2.java#L114-L139","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nList<SpanEvent> events = span.getSpanEventList();\nlong keyTime = grpcSpanProcessor.keyTime(events);\n\n// after\nList<SpanEvent> events = span.getSpanEventList();\nevents.removeIf(Objects::isNull);\nlong keyTime = events.isEmpty() ? span.getStartTime() : events.get(0).getStartTime();","handlingStrategy":"validation","validationCode":"if (spanEventList != null && !spanEventList.isEmpty() && spanEventList.get(0) == null) {\n    spanEventList.removeIf(Objects::isNull); // sanitize before key-time computation\n}","typeGuard":null,"tryCatchPattern":"try {\n    long keyTime = processor.keyTime(span.getSpanEventList());\n} catch (IllegalStateException e) {\n    logger.warn(\"Null SpanEvent in list for span {}\", span.getSpanId(), e);\n    keyTime = span.getStartTime();\n}","preventionTips":["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."],"tags":["java","null-pointer","internal-invariant","grpc","tracing"],"backgroundTag":"null-argument","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}