apache/beam · error · AssertionError

Encountered unhashable element

Error message

Encountered unhashable element: {}.

What it means

assertUnhashableCountEqual compares multisets of possibly-unhashable Beam PCollection elements by converting each element to a hashable representation via _to_hashable. The helper handles dicts/lists/sets and numpy arrays, but raises AssertionError for any other unhashable type it does not know how to convert.

Solutions

  1. Make the element type hashable by implementing __hash__ (and __eq__) on the custom class
  2. Convert unsupported unhashable containers to supported ones (dict/list/set/ndarray) before asserting
  3. Use a different assertion (e.g., sort elements by a key and compare lists) for exotic types

Example fix

# before
assert_that(res, extra_assertion=assertUnhashableCountEqual(expected_custom_objects))
# after
class MyRecord:
  def __eq__(self, other): return self.x == other.x
  def __hash__(self): return hash(self.x)  # now hashable; helper won't raise
assert_that(res, extra_assertion=assertUnhashableCountEqual(expected))
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np
def all_elements_supported(elements) -> bool:
    return all(
        isinstance(e, (dict, list, set, frozenset, np.ndarray)) or
        (hasattr(e, '__hash__') and hash(e) is not None)
        for e in elements
    )

Type guard

def is_hashable_or_supported(el) -> bool:
    import numpy as np
    if isinstance(el, (dict, list, set, frozenset, np.ndarray)):
        return True
    try:
        hash(el)
        return True
    except TypeError:
        return False

Try / catch

try:
    assertUnhashableCountEqual(expected, actual)
except AssertionError as e:
    if 'Encountered unhashable element' in str(e):
        logging.error('Convert custom unhashable types to dict/list/ndarray or add __hash__.')
    else:
        raise

Prevention

When it happens

Trigger: Calling assertUnhashableCountEqual with expected or actual elements containing unhashable objects other than dict/list/set/np.ndarray — e.g. custom class instances, or containers nested beyond the cases _to_hashable handles recursively.

Common situations: Testing pipelines outputting custom class instances or sets of custom objects; comparing elements containing nested custom containers; using the assertion on types the helper wasn't designed for.

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/ead0e5f698c4d1c9. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/testing/extra_assertions.py:53

    try:
      hash(element)
      return element
    except TypeError:
      pass

    if isinstance(element, list):
      return tuple(self._to_hashable(e) for e in element)

    if isinstance(element, dict):
      hashable_elements = []
      for key, value in sorted(element.items(), key=lambda t: hash(t[0])):
        hashable_elements.append((key, self._to_hashable(value)))
      return tuple(hashable_elements)

    if isinstance(element, np.ndarray):
      return element.tobytes()

    raise AssertionError("Encountered unhashable element: {}.".format(element))

View on GitHub (pinned to 12126d8942)