{"record":{"id":"1f96403602b6c542","repo":"openzipkin/zipkin","slug":"don-t-use-test-data-that-results-in-indeterministi","errorCode":null,"errorMessage":"Don't use test data that results in indeterministic ordering:\nl={}, r={}","messagePattern":"Don't use test data that results in indeterministic ordering:\nl=(.+?), r=(.+?)","errorType":"validation","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"zipkin-tests/src/main/java/zipkin2/storage/ITStorage.java","lineNumber":234,"sourceCode":"      int traceId = l.traceId().compareTo(r.traceId());\n      if (traceId != 0) return traceId;\n      int id = l.id().compareTo(r.id());\n      if (id != 0) return id;\n      int shared = Boolean.compare(TRUE.equals(l.shared()), TRUE.equals(r.shared()));\n      if (shared != 0) return shared;\n\n      if (l.name() != null && r.name() != null) {\n        int name = l.name().compareTo(r.name());\n        if (name != 0) return name;\n      }\n\n      int timestamp = Long.compare(l.timestampAsLong(), r.timestampAsLong());\n      if (timestamp != 0) return timestamp;\n\n      int duration = Long.compare(l.durationAsLong(), r.durationAsLong());\n      if (duration != 0) return duration;\n\n      throw new AssertionError(\"Don't use test data that results in indeterministic ordering:\\n\" +\n        \"l=\" + l + \", r=\" + r);\n    });\n    return result;\n  }\n}\n","sourceCodeStart":216,"sourceCodeEnd":240,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin-tests/src/main/java/zipkin2/storage/ITStorage.java#L216-L240","documentation":"ITStorage's span-sorting comparator throws AssertionError when two spans compare equal on every discriminator (same names, timestamps, and durations). The sharedSortWithTimestamp helper relies on test data having deterministic order; ties mean the assertion 'same span seen twice or ambiguous data' cannot be verified reliably, so the harness flags the test data itself as broken.","triggerScenarios":"Calling the sort helper (used by assertSameTags/assertSpanCount style checks) with test traces containing two spans that share name, timestamp, duration, and have null-vs-null ordering fields — i.e. identical by every compared key.","commonSituations":"Custom integration tests that insert duplicate spans or reuse TestObjects spans without varying timestamps; batch-span-consumer tests that accept the same span twice; test data generators that zero out timestamps.","solutions":["Make test spans distinguishable: give each a distinct name, timestamp, or duration.","De-duplicate the span list before sorting/asserting (the duplicate is usually the bug in the test).","If you genuinely insert the same span twice, assert on counts separately instead of relying on the sorted comparison."],"exampleFix":"// before: two spans with identical name/timestamp/duration\nSpan a = span.toBuilder().build();\nSpan b = span.toBuilder().build();\n\n// after: vary the timestamp\nSpan a = span.toBuilder().build();\nSpan b = span.toBuilder().timestamp(span.timestampAsLong() + 1000).build();","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (Span s : spans) {\n  String key = s.name() + \":\" + s.timestampAsLong() + \":\" + s.durationAsLong();\n  if (!seen.add(key)) throw new AssertionError(\"duplicate span in test data: \" + key);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Design test traces so every span differs in name, timestamp, or duration","De-duplicate spans before asserting on sorted order"],"tags":["testing","assertion","test-data","ordering","determinism"],"backgroundTag":null,"analyzedSha":"878ce2a1fad54ca941d17fdcf2e1d924b148eb1f","analyzedAt":"2026-08-14T15:17:09.895Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}