{"record":{"id":"fc17b7b9177dda6e","repo":"apache/beam","slug":"failed-assert-unmatched-elements-in-window","errorCode":null,"errorMessage":"Failed assert: unmatched elements {} in window {}","messagePattern":"Failed assert: unmatched elements (.+?) in window (.+?)","errorType":"exception","errorClass":"BeamAssertException","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/testing/util.py","lineNumber":144,"sourceCode":"            'Failed assert: element {} not found in window ' \\\n            '{}:{}'.format(actual, window_key, _expected[window_key]))\\\n\n    # Run the matcher for each window and value pair. Fails if the\n    # windowed_value is not a TestWindowedValue.\n    for windowed_value in value:\n      if not isinstance(windowed_value, TestWindowedValue):\n        raise BeamAssertException(\n            'Failed assert: Received element {} is not of type ' \\\n            'TestWindowedValue. Did you forget to set reify_windows=True ' \\\n            'on the assertion?'.format(windowed_value))\n      match(windowed_value)\n\n    # Finally, some elements may not have been matched. Assert that we removed\n    # all the elements that we received from the expected list. If the list is\n    # non-empty, then there are unmatched elements.\n    for win in _expected:\n      if _expected[win]:\n        raise BeamAssertException(\n            'Failed assert: unmatched elements {} in window {}'.format(\n                _expected[win], win))\n\n\ndef equal_to_per_window(expected_window_to_elements):\n  \"\"\"Matcher used by assert_that to check to assert expected windows.\n\n  The 'assert_that' statement must have reify_windows=True. This assertion works\n  when elements are emitted and are finally checked at the end of the window.\n\n  Arguments:\n    expected_window_to_elements: A dictionary where the keys are the windows\n      to check and the values are the elements associated with each window.\n  \"\"\"\n\n  return _EqualToPerWindowMatcher(expected_window_to_elements)\n\n","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/testing/util.py#L126-L162","documentation":"After matching all received elements, equal_to_per_window checks that every window's expected list is empty (all expected elements were consumed by actual matches). Any leftover expected elements for a window means the pipeline produced fewer/different elements than expected, so BeamAssertException lists the unmatched elements and the window.","triggerScenarios":"The expected dict contains an element (or an entire window) that never appeared in the actual output — e.g. expected {win: ['a','b']} but only 'a' was emitted, or an expected window received no data at all.","commonSituations":"Pipeline drops or filters records that the test expected; partial batch/test data; a transform emits fewer outputs (e.g. flat_map skipping items); duplicated windows in expectations that never receive data.","solutions":["Remove or correct the unmatched expected elements/windows to reflect actual output.","Debug why the pipeline did not emit those elements (check filters, conditions, input data).","Add logging before the assertion to dump actual elements per window."],"exampleFix":"// before\nassert_that(pcoll, equal_to_per_window({win: ['a', 'b']}), reify_windows=True)  # only 'a' emitted\n// after\nassert_that(pcoll, equal_to_per_window({win: ['a']}), reify_windows=True)","handlingStrategy":"validation","validationCode":"# cross-check expected totals against input record counts\nexpected_total = sum(len(v) for v in expected.values())\nassert expected_total <= num_input_records, 'more expected than input elements'","typeGuard":"def no_leftover_expectations(expected) -> bool:\n    return all(not v for v in expected.values())  # after a completed match","tryCatchPattern":"from apache_beam.testing.util import BeamAssertException\ntry:\n    assert_that(pcoll, equal_to_per_window(expected), reify_windows=True)\nexcept BeamAssertException as e:\n    if 'unmatched elements' in str(e):\n        logging.error('Missing outputs: %s', e)\n    else:\n        raise","preventionTips":["Account for filters/flat_maps that may drop records","Build expected windows only for windows that receive data","Keep test input data aligned with expectations (generate both from one fixture)"],"tags":["python","apache-beam","assertion","windowing","test"],"backgroundTag":"unexpected-response-shape","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"}