{"record":{"id":"61fb1dc59f7ebb96","repo":"apache/beam","slug":"getpositionforfractionconsumed-is-not-applicable-to-an","errorCode":null,"errorMessage":"getPositionForFractionConsumed is not applicable to an unbounded range: ","messagePattern":"getPositionForFractionConsumed is not applicable to an unbounded range: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/io/range/OffsetRangeTracker.java","lineNumber":169,"sourceCode":"    }\n    if (splitOffset < startOffset || splitOffset >= stopOffset) {\n      LOG.debug(\n          \"Refusing to split {} at {}: proposed split position out of range\", this, splitOffset);\n      return false;\n    }\n    LOG.debug(\"Agreeing to split {} at {}\", this, splitOffset);\n    this.stopOffset = splitOffset;\n    return true;\n  }\n\n  /**\n   * Returns a position {@code P} such that the range {@code [start, P)} represents approximately\n   * the given fraction of the range {@code [start, end)}. Assumes that the density of records in\n   * the range is approximately uniform.\n   */\n  public synchronized long getPositionForFractionConsumed(double fraction) {\n    if (stopOffset == OFFSET_INFINITY) {\n      throw new IllegalArgumentException(\n          \"getPositionForFractionConsumed is not applicable to an unbounded range: \" + this);\n    }\n    return (long) Math.floor(startOffset + fraction * (stopOffset - startOffset));\n  }\n\n  @Override\n  public synchronized double getFractionConsumed() {\n    if (!isStarted()) {\n      return 0.0;\n    } else if (isDone()) {\n      return 1.0;\n    } else if (stopOffset == OFFSET_INFINITY) {\n      return 0.0;\n    } else if (lastRecordStart >= stopOffset) {\n      return 1.0;\n    } else {\n      // E.g., when reading [3, 6) and lastRecordStart is 4, that means we consumed 3 of 3,4,5\n      // which is (4 - 3) / (6 - 3) = 33%.","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/io/range/OffsetRangeTracker.java#L151-L187","documentation":"OffsetRangeTracker.getPositionForFractionConsumed computes a position corresponding to a fraction of a bounded range [start, stop). Fraction-based progress is meaningless for an unbounded range (stop == Long.MAX_VALUE / OFFSET_INFINITY), so the method throws IllegalArgumentException in that case.","triggerScenarios":"Calling getPositionForFractionConsumed(fraction) on a tracker whose range was created with OFFSET_INFINITY (e.g. OffsetRangeTracker(Long.MAX_VALUE) or an unbounded IO like Pub/Sub-backed sources).","commonSituations":"Streaming pipelines or tests (e.g. testEverythingWithUnboundedRange) that query fractional progress on unbounded sources, or generic monitoring code that assumes all sources are bounded.","solutions":["Check tracker.getStopOffset() != Long.MAX_VALUE before calling getPositionForFractionConsumed.","Use getFractionConsumed() on the tracker instead, which handles unbounded ranges.","Restrict fraction-based progress reporting to bounded (batch) sources.","For unbounded sources, estimate progress from records processed or watermark rather than range fraction."],"exampleFix":"// before\nlong pos = tracker.getPositionForFractionConsumed(0.5);\n// after\nif (tracker.getStopOffset() != Long.MAX_VALUE) {\n  long pos = tracker.getPositionForFractionConsumed(0.5);\n} else {\n  Double frac = tracker.getFractionConsumed(); // handles unbounded\n}","handlingStrategy":"validation","validationCode":"if (tracker.getStopOffset() != Long.MAX_VALUE) { long pos = tracker.getPositionForFractionConsumed(f); }","typeGuard":"boolean isBounded = tracker.getStopOffset() != Long.MAX_VALUE;","tryCatchPattern":"try { pos = tracker.getPositionForFractionConsumed(f); } catch (IllegalArgumentException e) { pos = -1; /* unbounded */ }","preventionTips":["Prefer getFractionConsumed(), which handles unbounded ranges","Branch on source boundedness (BoundedSource vs UnboundedSource) before fraction math","Avoid fraction-based progress for streaming pipelines"],"tags":["apache-beam","unbounded-range","progress-tracking"],"backgroundTag":"unsupported-operation","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"}