{"record":{"id":"55411f2d52eae7ef","repo":"apache/beam","slug":"first-entry-is-null-when-initial-sequence-is-set","errorCode":null,"errorMessage":"First entry is null when initial sequence is set.","messagePattern":"First entry is null when initial sequence is set\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/ordered/src/main/java/org/apache/beam/sdk/extensions/ordered/combiner/SequenceRangeAccumulator.java","lineNumber":135,"sourceCode":"        && lowerRange.getValue().getLeft() > sequence) {\n      // The sequence is in the middle of the range. Adjust it.\n      data.remove(lowerRange.getKey());\n      data.put(\n          sequence,\n          Pair.of(\n              lowerRange.getValue().getKey(), max(timestamp, lowerRange.getValue().getValue())));\n    }\n    data.subMap(Long.MIN_VALUE, sequence).clear();\n  }\n\n  public ContiguousSequenceRange largestContinuousRange() {\n    if (initialSequence == null) {\n      return ContiguousSequenceRange.EMPTY;\n    }\n\n    Entry<Long, Pair<Long, Instant>> firstEntry = data.firstEntry();\n    if (firstEntry == null) {\n      throw new IllegalStateException(\"First entry is null when initial sequence is set.\");\n    }\n    Long start = firstEntry.getKey();\n    Long end = firstEntry.getValue().getLeft();\n    Instant latestTimestamp = firstEntry.getValue().getRight();\n    // Upper bound is inclusive, but the ContiguousSequenceRange's end is exclusive.\n    // The numeric overflow is prevented by dropping the value of Long.MAX.\n    return ContiguousSequenceRange.of(start, end + 1, latestTimestamp);\n  }\n\n  public int numberOfRanges() {\n    return data.size();\n  }\n\n  public void merge(SequenceRangeAccumulator another) {\n    if (this.initialSequence != null\n        && another.initialSequence != null\n        && !this.initialSequence.equals(another.initialSequence)) {\n      throw new IllegalStateException(","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/ordered/src/main/java/org/apache/beam/sdk/extensions/ordered/combiner/SequenceRangeAccumulator.java#L117-L153","documentation":"SequenceRangeAccumulator.largestContinuousRange() checks that when initialSequence is set, at least one data entry exists. Hitting this IllegalStateException means the accumulator claims an initial sequence was seen but its internal TreeMap is empty — an impossible state that signals corrupted accumulator state (e.g. data was dropped or deserialized incorrectly).","triggerScenarios":"Calling result()/largestContinuousRange() on an accumulator where initialSequence != null but data is empty — usually after a faulty custom codec/clone of the accumulator, or external mutation of accumulator fields.","commonSituations":"Custom accumulation/encoding of accumulators losing the data map but keeping initialSequence; reflection-based mutation in tests; combining logic that clears data without resetting initialSequence.","solutions":["Fix the accumulator codec (encode/decode) so data entries are preserved along with initialSequence.","Reset initialSequence to null whenever data is cleared, keeping the invariant in sync.","Avoid external mutation; use the public add()/merge() API only.","If reachable from a library bug, upgrade the beam extensions/ordered artifact to a fixed version."],"exampleFix":"// before\nacc.data.clear(); // initialSequence left non-null\n// after\nacc.data.clear();\nacc.initialSequence = null; // restore invariant","handlingStrategy":"validation","validationCode":"if (acc.getInitialSequence() != null && acc.isEmpty()) {\n  throw new IllegalStateException(\"corrupt accumulator: initialSequence set but no data entries\");\n}","typeGuard":"static boolean isConsistent(SequenceRangeAccumulator acc) {\n  return acc.getInitialSequence() == null || !acc.isEmpty();\n}","tryCatchPattern":"try {\n  ContiguousSequenceRange r = acc.largestContinuousRange();\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"First entry is null\")) {\n    throw new IllegalStateException(\"accumulator data lost in codec/merge; fix encode/decode\", e);\n  }\n  throw e;\n}","preventionTips":["Preserve the data map when encoding/decoding accumulators","Clear initialSequence whenever data is cleared","Round-trip-test accumulator serialization in unit tests"],"tags":["apache-beam","combiner","state-corruption","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}