apache/beam · error · BeamAssertException

Failed assert: %r == %r

Error message

Failed assert: %r == %r

What it means

This is the failure path of the equal_to() matcher's _equal function: after matching actual elements against expected, if there are unexpected actual elements or missing expected elements, it raises BeamAssertException with a formatted 'expected == actual' message, appending the specific unexpected and/or missing elements when present.

Solutions

  1. Read the 'missing elements'/'unexpected elements' suffix of the message and update either the expectation or the pipeline accordingly.
  2. Verify element types match exactly (str vs bytes, int vs float).
  3. Compare against actual output by logging the PCollection contents before the assertion.

Example fix

// before
assert_that(pcoll, equal_to(['a', 'b']))  # pipeline emits ['a', 'c']
// after
assert_that(pcoll, equal_to(['a', 'c']))
Defensive patterns

Strategy: try-catch

Validate before calling

# pre-check: run the pipeline logic on sample data locally and compare
# expected_set = set(expected); actual_set = set(dry_run_output)
# assert expected_set == actual_set

Try / catch

from apache_beam.testing.util import BeamAssertException
try:
    assert_that(pcoll, equal_to(expected))
except BeamAssertException as e:
    logging.error('Pipeline output mismatch: %s', e)
    raise

Prevention

When it happens

Trigger: assert_that(pcoll, equal_to([...])) where the actual output differs from the expected list in any way: missing items, extra items, wrong order handled via multiset matching, or type-differing values (e.g. '1' vs 1).

Common situations: Ordinary test failures where pipeline output diverges from expectations; encoding differences (bytes vs str); duplicate counts differing; NaN or unhashable values handled differently across runners.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/testing/util.py:205

    # 2) As a fallback if we encounter a TypeError in python 3. this method
    #    works on collections that have different types.
    unexpected = []
    for element in actual:
      found = False
      for i, v in enumerate(expected_list):
        if equals_fn(v, element):
          found = True
          expected_list.pop(i)
          break
      if not found:
        unexpected.append(element)
    if unexpected or expected_list:
      msg = 'Failed assert: %r == %r' % (expected, actual)
      if unexpected:
        msg = msg + ', unexpected elements %r' % unexpected
      if expected_list:
        msg = msg + ', missing elements %r' % expected_list
      raise BeamAssertException(msg)

  return _equal


def row_namedtuple_equals_fn(expected, actual, fallback_equals_fn=None):
  """
  equals_fn which can be used by equal_to which treats Rows and
  NamedTuples as equivalent types. This can be useful since Beam converts
  Rows to NamedTuples when they are sent across portability layers, so a Row
  may be converted to a NamedTuple automatically by Beam.
  """
  if fallback_equals_fn is None:
    fallback_equals_fn = lambda e, a: e == a
  if type(expected) is not pvalue.Row and not _is_named_tuple(expected):
    return fallback_equals_fn(expected, actual)
  if type(actual) is not pvalue.Row and not _is_named_tuple(actual):
    return fallback_equals_fn(expected, actual)

View on GitHub (pinned to 12126d8942)