Skip to content

Topic/NamedBarrierValue from_checkpoint aliases the checkpoint container instead of copying #7992

@vidigoat

Description

@vidigoat

Description

Topic.from_checkpoint and NamedBarrierValue.from_checkpoint assign the checkpoint's container directly to the new channel instead of copying it:

# topic.py
empty.values = checkpoint
# named_barrier_value.py
empty.seen = checkpoint

BaseChannel.from_checkpoint documents that "If the checkpoint contains complex data structures, they should be copied", and the channels' own copy() methods do copy (self.values.copy(), self.seen.copy()), but from_checkpoint does not. So two channels restored from the same checkpoint object share the same list/set, and an in-place update to one mutates the checkpoint and the sibling.

Reproduction

from langgraph.channels.topic import Topic

source = Topic(str, accumulate=True)
source.update(["a", "b"])
checkpoint = source.checkpoint()

one = Topic(str, accumulate=True).from_checkpoint(checkpoint)
two = Topic(str, accumulate=True).from_checkpoint(checkpoint)
one.update(["c"])

print(two.get())     # ['a', 'b', 'c']  -> expected ['a', 'b']
print(checkpoint)    # ['a', 'b', 'c']  -> checkpoint was mutated

NamedBarrierValue (and NamedBarrierValueAfterFinish) behave the same way with their seen set. This matters when a single loaded checkpoint is reused across restores (replay / forking a thread): an accumulate=True topic or a barrier value can retroactively corrupt the persisted checkpoint.

Expected

from_checkpoint should copy the container, like copy() already does, so restored channels are independent of the checkpoint and of each other.

System info

langgraph main; the affected code is in langgraph/channels/topic.py and langgraph/channels/named_barrier_value.py.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions