apache/beam · error · ValueError

Source is too trivial since it produces only %d values. Plea

Error message

Source is too trivial since it produces only %d values. Please give a source that reads at least 2 values.

What it means

Raised by assert_reentrant_reads_succeed when the supplied BoundedSource produces fewer than 2 values over the given [start_position, stop_position) range. The reentrancy test needs at least 2 records so it can interrupt a read partway, perform a second (reentrant) read, and verify both reads are correct; a trivial source cannot exercise this. It is a precondition failure on the test input, not a bug in the source's read logic.

Source

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

    source_info (Tuple[~apache_beam.io.iobase.BoundedSource, int, int]):
      a three-tuple that gives the reference
      :class:`~apache_beam.io.iobase.BoundedSource`, position to start reading
      at, and a position to stop reading at.

  Raises:
    ValueError: if source is too trivial or reentrant read result
      in an incorrect read.
  """

  source, start_position, stop_position = source_info
  assert isinstance(source, iobase.BoundedSource)

  expected_values = [
      val for val in source.read(
          source.get_range_tracker(start_position, stop_position))
  ]
  if len(expected_values) < 2:
    raise ValueError(
        'Source is too trivial since it produces only %d '
        'values. Please give a source that reads at least 2 '
        'values.' % len(expected_values))

  for i in range(1, len(expected_values) - 1):
    read_iter = source.read(
        source.get_range_tracker(start_position, stop_position))
    original_read = []
    for _ in range(i):
      original_read.append(next(read_iter))

    # Reentrant read
    reentrant_read = [
        val for val in source.read(
            source.get_range_tracker(start_position, stop_position))
    ]

    # Continuing original read.

View on GitHub (pinned to 12126d8942)

Solutions

  1. Provide a source/fixture that produces at least 2 records for the given range.
  2. Widen the [start_position, stop_position) range passed in source_info so it spans multiple records.
  3. Skip reentrancy testing for genuinely single-record sources and use a larger test input instead.

Example fix

// before
assert_reentrant_reads_succeed((src, 0, 1))
// after
assert_reentrant_reads_succeed((src, 0, src.estimate_size()))
Defensive patterns

Strategy: validation

Validate before calling

vals = list(source.read(source.get_range_tracker(start, stop)))
if len(vals) < 2:
    pytest.skip("source trivial over this range; enlarge range or fixture")

Type guard

def is_testable_range(source, start, stop):
    return len(list(source.read(source.get_range_tracker(start, stop)))) >= 2

Try / catch

try:
    source_test_utils.assert_reentrant_reads_succeed((src, start, stop))
except ValueError as e:
    if "too trivial" in str(e):
        pytest.skip(str(e))
    raise

Prevention

When it happens

Trigger: Calling assert_reentrant_reads_succeed((source, start_position, stop_position)) where a full read of the source over that range yields 0 or 1 values.

Common situations: Testing with a tiny fixture file or a narrow position range in a unit test, so the source naturally produces a single record over the selected range.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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