{"record":{"id":"f697e117d0da8595","repo":"pinpoint-apm/pinpoint","slug":"trace-v3-span-event-requires-absolute-start-end-ti","errorCode":null,"errorMessage":"TRACE_V3 span event requires absolute start/end time","messagePattern":"TRACE_V3 span event requires absolute start/end time","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"commons-server/src/main/java/com/navercorp/pinpoint/common/server/bo/SpanEventBo.java","lineNumber":117,"sourceCode":"     */\n    public int getEndElapsed() {\n        return endElapsed;\n    }\n\n    public void setEndElapsed(int endElapsed) {\n        this.endElapsed = endElapsed;\n    }\n\n    /**\n     * Sets elapsed-only span event time for pre-V3 data.\n     * startElapsedMillis is the offset from the parent span/chunk start, and endElapsedMillis\n     * is the event duration.\n     */\n    public void setTraceTime(int version, int startElapsedMillis, int endElapsedMillis) {\n        setVersion((byte) version);\n\n        if (version == SpanVersion.TRACE_V3) {\n            throw new IllegalArgumentException(\"TRACE_V3 span event requires absolute start/end time\");\n        }\n\n        this.startTime = DEFAULT_START_TIME;\n        this.endTime = DEFAULT_END_TIME;\n        this.startElapsed = startElapsedMillis;\n        this.endElapsed = endElapsedMillis;\n    }\n\n    /**\n     * Sets absolute span event time for TRACE_V3 data.\n     * startTime/endTime are epoch nanos. startElapsedMillis is retained as the compatibility\n     * offset from the parent span/chunk start; endElapsedMillis is derived from endTime-startTime.\n     */\n    public void setTraceTime(int version, long startTime, long endTime, int startElapsedMillis) {\n        setVersion((byte) version);\n\n        if (version != SpanVersion.TRACE_V3) {\n            throw new IllegalArgumentException(\"absolute start/end time is only supported for TRACE_V3 span events\");","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/commons-server/src/main/java/com/navercorp/pinpoint/common/server/bo/SpanEventBo.java#L99-L135","documentation":"This SpanEventBo.setTraceTime overload (startElapsedMillis/endElapsedMillis) is only valid for relative-time trace formats (TRACE_V2 and older). TRACE_V3 span events store absolute start/end nanos, so the method explicitly rejects TRACE_V3 because it would discard the absolute-time model.","triggerScenarios":"Calling setTraceTime(version, startElapsedMillis, endElapsedMillis) with version == SpanVersion.TRACE_V3, e.g. while decoding a span event via readSpanEvent or bind when the relative-elapsed decoder path is applied to V3 data.","commonSituations":"A decoder bug where the V2 relative-time path is chosen for V3-encoded rows; agents and servers at mismatched versions during a TRACE_V2 to TRACE_V3 migration; test code reusing the V2 setter for V3 objects.","solutions":["Use the absolute-time overload setTraceTime(version, startTime, endTime, startElapsedMillis) for TRACE_V3 span events","Check which decoder branch (V2 vs V3) is invoked in readSpanEvent and route V3 rows to the V3 path","Ensure agent and collector/server versions agree on the trace format version"],"exampleFix":"// before\nspanEventBo.setTraceTime(SpanVersion.TRACE_V3, startElapsed, endElapsed);\n// after\nspanEventBo.setTraceTime(SpanVersion.TRACE_V3, startNanos, endNanos, startElapsed);","handlingStrategy":"validation","validationCode":"if (version != SpanVersion.TRACE_V3) {\n    spanEventBo.setTraceTime(version, startElapsedMillis, endElapsedMillis);\n} else {\n    spanEventBo.setTraceTime(version, startNanos, endNanos, startElapsedMillis);\n}","typeGuard":"boolean supportsRelativeElapsed(int version) {\n    return version != SpanVersion.TRACE_V3;\n}","tryCatchPattern":"try {\n    spanEventBo.setTraceTime(version, startElapsed, endElapsed);\n} catch (IllegalArgumentException e) {\n    logger.warn(\"Relative time not allowed for version \" + version, e);\n}","preventionTips":["Use the absolute-time overload for V3 and the elapsed overload otherwise","Ensure decoder branches are keyed on SpanVersion, not on byte-layout heuristics","Test the readSpanEvent path with both V2 and V3 fixtures"],"tags":["java","serialization","trace-versioning"],"backgroundTag":"incompatible-source-type","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"}