apache/beam · error · ValueError

Expected split of source %r at fraction %r to be successful

Error message

Expected split of source %r at fraction %r to be successful after reading %d elements. But the split failed.

What it means

Raised by _assert_split_at_fraction_behavior when the test expects the split to succeed (ExpectedSplitOutcome.MUST_SUCCEED_AND_BE_CONSISTENT) but RangeTracker.try_split returned None after reading num_items_to_read_before_split elements at the requested fraction. This means the source/RangeTracker refused a dynamic split that Beam's harness expects to be possible, defeating work rebalancing. It is an expectation mismatch between the test's declared outcome and the tracker's actual behavior.

Source

Thrown at sdks/python/apache_beam/io/source_test_utils.py:328

          'RangeTracker must be the same as the returned split '
          'position. Observed %r and %r which are different.' %
          (range_tracker.stop_position() % (split_result[0], )))

    if split_fraction < 0 or split_fraction > 1:
      raise ValueError(
          'Split fraction must be within the range [0,1]',
          'Observed split fraction was %r.' % (split_result[1], ))

  stop_position_after_split = range_tracker.stop_position()
  if split_result and stop_position_after_split == stop_position_before_split:
    raise ValueError(
        'Stop position %r did not change after a successful '
        'split of source %r at fraction %r.' %
        (stop_position_before_split, source, split_fraction))

  if expected_outcome == ExpectedSplitOutcome.MUST_SUCCEED_AND_BE_CONSISTENT:
    if not split_result:
      raise ValueError(
          'Expected split of source %r at fraction %r to be '
          'successful after reading %d elements. But '
          'the split failed.' %
          (source, split_fraction, num_items_to_read_before_split))
  elif expected_outcome == ExpectedSplitOutcome.MUST_FAIL:
    if split_result:
      raise ValueError(
          'Expected split of source %r at fraction %r after '
          'reading %d elements to fail. But splitting '
          'succeeded with result %r.' % (
              source,
              split_fraction,
              num_items_to_read_before_split,
              split_result))

  elif (expected_outcome
        != ExpectedSplitOutcome.MUST_BE_CONSISTENT_IF_SUCCEEDS):
    raise ValueError('Unknown type of expected outcome: %r' % expected_outcome)

View on GitHub (pinned to 12126d8942)

Solutions

  1. Implement try_split in the source's RangeTracker so it actually splits at the suggested position instead of always returning None.
  2. If the source legitimately cannot split, change the test expectation to ExpectedSplitOutcome.MUST_FAIL or DONOT_KNOW.
  3. Verify the chosen split_fraction leaves a non-empty remainder range (avoid splitting at ~0.0 or ~1.0 boundaries that the tracker rejects).
  4. Ensure position_at_fraction maps the fraction to a valid position inside [start, stop) so the split isn't declined as out-of-range.

Example fix

// before: always refuse split
def try_split(self, fraction):
  return None
// after
def try_split(self, fraction):
  pos = self.position_at_fraction(fraction)
  if pos is None or pos <= self.start_position() or pos >= self.stop_position():
    return None
  self._stop = pos
  return (pos, fraction)
Defensive patterns

Strategy: validation

Validate before calling

pos = tracker.position_at_fraction(f)
will_split = tracker.try_split(pos) is not None
if expected_outcome == ExpectedSplitOutcome.MUST_SUCCEED_AND_BE_CONSISTENT and not will_split:
    pytest.fail("tracker refuses expected split at fraction %r" % f)

Type guard

def supports_splitting(source):
    return not type(source.get_range_tracker(None, None)).try_split.__qualname__.startswith("RangeTracker") or True

Try / catch

try:
    source_test_utils.assert_split_at_fraction_behavior(src, n, f, outcome)
except ValueError as e:
    if "to be successful" in str(e) or "the split failed" in str(e):
        logger.error("tracker declined expected split: %s", e)
    raise

Prevention

When it happens

Trigger: assert_split_at_fraction_behavior(source, n, fraction, ExpectedSplitOutcome.MUST_SUCCEED_AND_BE_CONSISTENT) where the source's RangeTracker returns None from try_split at that point — e.g. a tracker that never supports splitting, or rejects splits too close to start/stop boundaries.

Common situations: Custom sources that conservatively return None from try_split (unsplittable), split_fraction chosen where remaining range is too small, or sources whose RangeTracker disables splitting below a size threshold while the test asserts success.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/5071ecc81dff0f13. Report an issue: GitHub.