{"record":{"id":"81fee9f94f1196b8","repo":"apache/beam","slug":"record-at-a-split-point-has-same-offset-as-the-previous","errorCode":null,"errorMessage":"Record at a split point has same offset as the previous split point: previous split point at %d, current record starts at %d","messagePattern":"Record at a split point has same offset as the previous split point: previous split point at (.+?), current record starts at (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/io/range/OffsetRangeTracker.java","lineNumber":112,"sourceCode":"              \"Trying to return record [starting at %d] which is before the start offset [%d]\",\n              recordStart, startOffset));\n    }\n    if (recordStart < lastRecordStart) {\n      throw new IllegalStateException(\n          String.format(\n              \"Trying to return record [starting at %d] \"\n                  + \"which is before the last-returned record [starting at %d]\",\n              recordStart, lastRecordStart));\n    }\n\n    if (lastRecordStart == -1) {\n      startOffset = recordStart;\n    }\n    lastRecordStart = recordStart;\n\n    if (isAtSplitPoint) {\n      if (recordStart == offsetOfLastSplitPoint) {\n        throw new IllegalStateException(\n            String.format(\n                \"Record at a split point has same offset as the previous split point: \"\n                    + \"previous split point at %d, current record starts at %d\",\n                offsetOfLastSplitPoint, recordStart));\n      }\n      if (recordStart >= stopOffset) {\n        done = true;\n        return false;\n      }\n      offsetOfLastSplitPoint = recordStart;\n      ++splitPointsSeen;\n    }\n\n    return true;\n  }\n\n  @Override\n  public boolean trySplitAtPosition(Long splitOffset) {","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/io/range/OffsetRangeTracker.java#L94-L130","documentation":"OffsetRangeTracker considers some offsets 'split points' (records that should be split around). tryReturnRecordAt throws IllegalStateException if two consecutive split-point records start at the same offset, which would break the defer/split accounting invariant in the range tracker.","triggerScenarios":"Calling tryReturnRecordAt(recordStart, true) twice with identical recordStart values, i.e. two records both flagged as at a split point at the same offset; usually from a reader that marks every record as a split point or yields duplicates.","commonSituations":"Custom IO implementations where isAtSplitPoint is incorrectly computed (e.g. always true), or offset-based sources where the same boundary record is consumed twice.","solutions":["Fix the isAtSplitPoint computation so only true boundary records are flagged.","Deduplicate records so the same offset is never returned twice as a split point.","Review how offsets are advanced in the reader loop to ensure each offset is consumed once.","Compare with an existing Beam source (e.g.AvroIO/BoundedSource readers) for correct split-point semantics."],"exampleFix":"// before\nboolean isSplit = true; // wrong: every record flagged\ntracker.tryReturnRecordAt(offset, isSplit);\n// after\nboolean isSplit = (offset % recordInterval == 0);\ntracker.tryReturnRecordAt(offset, isSplit);","handlingStrategy":"validation","validationCode":"boolean isSplit = isTrueSplitPoint(offset); if (isSplit && offset == lastSplitOffset) { isSplit = false; }","typeGuard":null,"tryCatchPattern":"try { tracker.tryReturnRecordAt(offset, atSplit); } catch (IllegalStateException e) { LOG.error(\"duplicate split point at \" + offset, e); throw e; }","preventionTips":["Only mark genuine boundary records as split points","Deduplicate offsets before returning records","Mirror split-point logic from an existing Beam source"],"tags":["apache-beam","state-violation","offset-tracking"],"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"}