{"record":{"id":"ccf1322c0855571d","repo":"apache/beam","slug":"splitatfraction-test-completed-vacuously-no-non-trivial","errorCode":null,"errorMessage":"SplitAtFraction test completed vacuously: no non-trivial split fractions found","messagePattern":"SplitAtFraction test completed vacuously: no non-trivial split fractions found","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/source_test_utils.py","lineNumber":617,"sourceCode":"    stats = SplitFractionStatistics([], [])\n\n    assert_split_at_fraction_binary(\n        source, expected_items, i, 0.0, None, 1.0, None, stats)\n\n    if stats.successful_fractions:\n      any_successful_fractions = True\n    if stats.non_trivial_fractions:\n      any_non_trivial_fractions = True\n\n    all_non_trivial_fractions.append(stats.non_trivial_fractions)\n\n  if not any_successful_fractions:\n    raise ValueError(\n        'SplitAtFraction test completed vacuously: no '\n        'successful split fractions found')\n\n  if not any_non_trivial_fractions:\n    raise ValueError(\n        'SplitAtFraction test completed vacuously: no non-trivial split '\n        'fractions found')\n\n  if not perform_multi_threaded_test:\n    return\n\n  num_total_trials = 0\n  for i in range(len(expected_items)):\n    non_trivial_fractions = [2.0]  # 2.0 is larger than any valid fraction.\n    non_trivial_fractions.extend(all_non_trivial_fractions[i])\n    min_non_trivial_fraction = min(non_trivial_fractions)\n\n    if min_non_trivial_fraction == 2.0:\n      # This will not happen all the time. Otherwise previous test will fail\n      # due to vacuousness.\n      continue\n\n    num_trials = 0","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/source_test_utils.py#L599-L635","documentation":"Similar to the vacuous-success guard: if every successful split was trivial (primary or residual empty), the exhaustive test learned nothing, so it raises this ValueError. A non-trivial split requires both primary and residual ranges to contain at least one item.","triggerScenarios":"Calling assert_split_at_fraction_exhaustive where all successful splits occur only at fraction 0 or 1 (or at boundaries), yielding trivial primaries/residuals.","commonSituations":"Source whose try_split clamps split positions to range ends; RangeTracker allowing splits exactly at start/stop; two-item sources where interior fractions all fail; granularity of positions larger than the item count.","solutions":["Fix try_split to reject splits at or beyond the range boundaries instead of clamping to them, and require start < split < stop.","Test with a source/range containing several items so interior fractions exist.","Use OffsetRangeTracker or another reference implementation to compare behavior.","Reduce record granularity so fractions between 0 and 1 map to distinct interior positions."],"exampleFix":"// before\nsplit = min(self.stop, max(self.start, proposed))  # allows trivial splits\n// after\nif proposed <= self.start or proposed >= self.stop:\n  return None\nsplit = proposed","handlingStrategy":"validation","validationCode":"stats = source.split_at_fraction(0.5)\nif stats is not None and (stats[0] == start or stats[1] == stop):\n    pytest.skip('splits are only trivial; exhaustive test would be vacuous')","typeGuard":null,"tryCatchPattern":"try:\n    assert_split_at_fraction_exhaustive(source, start, stop)\nexcept ValueError as e:\n    if 'no non-trivial split fractions' in str(e):\n        pytest.fail(f'all successful splits are trivial: {e}')","preventionTips":["Reject split positions at range boundaries in try_split instead of clamping","Use sources/ranges with enough items that interior fractions exist","Keep position granularity finer than the item count"],"tags":["python","apache-beam","vacuous-test","split-at-fraction"],"backgroundTag":"empty-result-set","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"}