Skip to content

fix: AsyncRedisSaver cannot be constructed outside an async context (…#183

Merged
bsbodden merged 1 commit intomainfrom
bsb/issue-179
Apr 15, 2026
Merged

fix: AsyncRedisSaver cannot be constructed outside an async context (…#183
bsbodden merged 1 commit intomainfrom
bsb/issue-179

Conversation

@bsbodden
Copy link
Copy Markdown
Contributor

#179)

@bsbodden bsbodden requested a review from vishal-bala April 15, 2026 16:07
@bsbodden bsbodden self-assigned this Apr 15, 2026
@bsbodden bsbodden requested review from Copilot and removed request for vishal-bala April 15, 2026 16:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses Issue #179 by allowing Redis async checkpoint savers to be instantiated in synchronous code (no running event loop) and deferring event-loop capture until async setup.

Changes:

  • Defer loop initialization in AsyncRedisSaver / AsyncShallowRedisSaver from __init__ to asetup().
  • Add explicit runtime errors when synchronous wrapper methods are called before asetup() / async with.
  • Add regression tests covering construction outside an event loop and loop capture during asetup().

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
langgraph/checkpoint/redis/aio.py Defers loop capture to asetup() and adds “must be set up” guards for sync wrappers.
langgraph/checkpoint/redis/ashallow.py Same as above for shallow saver; adds “must be set up” guards for sync wrappers.
tests/test_async.py Adds regression tests for AsyncRedisSaver construction outside a running loop and loop capture in asetup() / context manager.
tests/test_shallow_async.py Adds analogous regression tests for AsyncShallowRedisSaver.
Comments suppressed due to low confidence (1)

langgraph/checkpoint/redis/aio.py:1343

  • The InvalidStateError guidance here points users to await checkpointer.get_channel_values(...), but that is the synchronous method name. This message should refer to the async API (e.g., await checkpointer.aget_channel_values(...)) to avoid confusing users who hit this error.
                raise asyncio.InvalidStateError(
                    "Synchronous calls to AsyncRedisSaver are only allowed from a "
                    "different thread. From the main thread, use the async interface."
                    "For example, use `await checkpointer.get_channel_values(...)`."
                )

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread langgraph/checkpoint/redis/aio.py
Comment thread langgraph/checkpoint/redis/ashallow.py
Comment thread langgraph/checkpoint/redis/ashallow.py
Comment thread tests/test_async.py Outdated
Comment thread tests/test_shallow_async.py Outdated
@bsbodden
Copy link
Copy Markdown
Contributor Author

Also addressed the suppressed low-confidence comment about the wrong method name in the get_channel_values() error message (aio.py:1343): the guidance string previously said await checkpointer.get_channel_values(...) (the sync name) — now correctly reads await checkpointer.aget_channel_values(...).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

langgraph/checkpoint/redis/ashallow.py:827

  • The InvalidStateError message is constructed from adjacent string literals and is missing a space after "use the async interface.", producing "interface.For example" at runtime. Add a space or merge the literals.
                raise asyncio.InvalidStateError(
                    "Synchronous calls to AsyncShallowRedisSaver are only allowed from a "
                    "different thread. From the main thread, use the async interface."
                    "For example, use `await checkpointer.aget_channel_values(...)`."
                )

langgraph/checkpoint/redis/ashallow.py:748

  • This InvalidStateError message is split across string literals without a space after "use the async interface.", so it will display as "interface.For example". Add a trailing space to the first literal or combine them.
                raise asyncio.InvalidStateError(
                    "Synchronous calls to AsyncShallowRedisSaver are only allowed from a "
                    "different thread. From the main thread, use the async interface."
                    "For example, use `await checkpointer.aget_tuple(...)` or `await "
                    "graph.ainvoke(...)`."

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread langgraph/checkpoint/redis/aio.py
Comment thread langgraph/checkpoint/redis/aio.py
@bsbodden
Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

@bsbodden bsbodden closed this Apr 15, 2026
@bsbodden bsbodden reopened this Apr 15, 2026
@bsbodden bsbodden merged commit 59de738 into main Apr 15, 2026
50 of 51 checks passed
Copilot stopped work on behalf of bsbodden due to an error April 15, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants