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
- Implement try_split in the source's RangeTracker so it actually splits at the suggested position instead of always returning None.
- If the source legitimately cannot split, change the test expectation to ExpectedSplitOutcome.MUST_FAIL or DONOT_KNOW.
- Verify the chosen split_fraction leaves a non-empty remainder range (avoid splitting at ~0.0 or ~1.0 boundaries that the tracker rejects).
- 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
- Implement try_split rather than unconditionally returning None
- Match test expectations (MUST_FAIL vs MUST_SUCCEED) to actual tracker capability
- Avoid split fractions at range boundaries the tracker legitimately rejects
- Ensure position_at_fraction yields an interior position of [start, stop)
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
- Split result must be a tuple that contains split position an
- After a successful split, the stop position of the RangeTrac
- Stop position %r did not change after a successful split of
- Error determining if %s allows dynamic splitting
- The first record [starting at %d] must be at a split point
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/5071ecc81dff0f13.
Report an issue: GitHub.