{"record":{"id":"ead0e5f698c4d1c9","repo":"apache/beam","slug":"encountered-unhashable-element","errorCode":null,"errorMessage":"Encountered unhashable element: {}.","messagePattern":"Encountered unhashable element: (.+?)\\.","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/testing/extra_assertions.py","lineNumber":53,"sourceCode":"    try:\n      hash(element)\n      return element\n    except TypeError:\n      pass\n\n    if isinstance(element, list):\n      return tuple(self._to_hashable(e) for e in element)\n\n    if isinstance(element, dict):\n      hashable_elements = []\n      for key, value in sorted(element.items(), key=lambda t: hash(t[0])):\n        hashable_elements.append((key, self._to_hashable(value)))\n      return tuple(hashable_elements)\n\n    if isinstance(element, np.ndarray):\n      return element.tobytes()\n\n    raise AssertionError(\"Encountered unhashable element: {}.\".format(element))\n","sourceCodeStart":35,"sourceCodeEnd":54,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/testing/extra_assertions.py#L35-L54","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make the element type hashable by implementing __hash__ (and __eq__) on the custom class","Convert unsupported unhashable containers to supported ones (dict/list/set/ndarray) before asserting","Use a different assertion (e.g., sort elements by a key and compare lists) for exotic types"],"exampleFix":"# before\nassert_that(res, extra_assertion=assertUnhashableCountEqual(expected_custom_objects))\n# after\nclass MyRecord:\n  def __eq__(self, other): return self.x == other.x\n  def __hash__(self): return hash(self.x)  # now hashable; helper won't raise\nassert_that(res, extra_assertion=assertUnhashableCountEqual(expected))","handlingStrategy":"type-guard","validationCode":"import numpy as np\ndef all_elements_supported(elements) -> bool:\n    return all(\n        isinstance(e, (dict, list, set, frozenset, np.ndarray)) or\n        (hasattr(e, '__hash__') and hash(e) is not None)\n        for e in elements\n    )","typeGuard":"def is_hashable_or_supported(el) -> bool:\n    import numpy as np\n    if isinstance(el, (dict, list, set, frozenset, np.ndarray)):\n        return True\n    try:\n        hash(el)\n        return True\n    except TypeError:\n        return False","tryCatchPattern":"try:\n    assertUnhashableCountEqual(expected, actual)\nexcept AssertionError as e:\n    if 'Encountered unhashable element' in str(e):\n        logging.error('Convert custom unhashable types to dict/list/ndarray or add __hash__.')\n    else:\n        raise","preventionTips":["Give test-element classes __hash__ and __eq__","Restrict test outputs to types supported by _to_hashable (dict/list/set/ndarray) or hashable builtins","Prefer sorted-key list comparison for custom objects"],"tags":["python","apache-beam","testing","assertions","hashability"],"backgroundTag":"invalid-argument-value","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"}