Checked other resources
Example Code
from langgraph.channels.named_barrier_value import NamedBarrierValue, NamedBarrierValueAfterFinish
names = {"a", "b"}
with_defer = NamedBarrierValueAfterFinish(str, set(names)); with_defer.update(["a"])
without = NamedBarrierValue(str, set(names)); without.update(["a"])
NamedBarrierValue(str, set(names)).from_checkpoint(with_defer.checkpoint()).seen
# ({'a'}, False) — defer removed: seen is the tuple itself; the barrier can
# never reach completeness, so the fan-in node is silently dead on that thread
NamedBarrierValueAfterFinish(str, set(names)).from_checkpoint(without.checkpoint())
# ValueError: not enough values to unpack (expected 2, got 1) — defer added
two = NamedBarrierValue(str, {"a", "b", "c"}); two.update(["a", "b"])
NamedBarrierValueAfterFinish(str, {"a", "b", "c"}).from_checkpoint(two.checkpoint()).seen
# 'a' or 'b' (set order) — with exactly two seen names the set unpacks
# SILENTLY into seen and finished strings
Error Message and Stack Trace (if applicable)
ValueError: not enough values to unpack (expected 2, got 1)
Only in the defer-added direction, and only when the number of seen names is not exactly two; the other cases are silent.
Description
NamedBarrierValue.checkpoint() returns the seen set; NamedBarrierValueAfterFinish.checkpoint() returns (seen, finished). Each from_checkpoint assumes its own shape, and the class is chosen from the node's current defer flag — so editing defer and resuming an existing thread restores the other variant's checkpoint into the wrong shape. Removing defer corrupts silently (the fan-in node never fires again on that thread); adding it raises at restore — except with exactly two seen names, where the set unpacks silently into seen and finished strings.
Expected: a barrier restored across a defer change keeps the names it had seen — each from_checkpoint accepting the other shape covers both directions. A branch with that fix and three tests (red on current main) is at main...serhiy-bzhezytskyy:langgraph:fix/defer-toggle-barrier-restore — external PRs are auto-closed here without an issue assignment, so it is left as a branch. The JS runtime has the same defect; langchain-ai/langgraphjs#2694 fixes it there in the same form.
System Info
langgraph 1.2.11.
Checked other resources
Example Code
Error Message and Stack Trace (if applicable)
Only in the defer-added direction, and only when the number of seen names is not exactly two; the other cases are silent.
Description
NamedBarrierValue.checkpoint()returns the seen set;NamedBarrierValueAfterFinish.checkpoint()returns(seen, finished). Eachfrom_checkpointassumes its own shape, and the class is chosen from the node's currentdeferflag — so editingdeferand resuming an existing thread restores the other variant's checkpoint into the wrong shape. Removingdefercorrupts silently (the fan-in node never fires again on that thread); adding it raises at restore — except with exactly two seen names, where the set unpacks silently intoseenandfinishedstrings.Expected: a barrier restored across a
deferchange keeps the names it had seen — eachfrom_checkpointaccepting the other shape covers both directions. A branch with that fix and three tests (red on currentmain) is at main...serhiy-bzhezytskyy:langgraph:fix/defer-toggle-barrier-restore — external PRs are auto-closed here without an issue assignment, so it is left as a branch. The JS runtime has the same defect; langchain-ai/langgraphjs#2694 fixes it there in the same form.System Info
langgraph1.2.11.