Repository navigation
fix(langgraph): stop reporting answered interrupts in getState - #3113
Mihir Inamdar (inamdarmihir) wants to merge 1 commit into
Conversation
Resuming one of several parallel interrupted tasks by interrupt id wrote its answer and the invoke result listed only the other interrupt, but getState() kept listing both: the snapshot read the recorded INTERRUPT write of every task, finished or not. The finished task was already left out of `next`, so its answered question appeared pending with no task to run. In the latest state, drop the interrupts of tasks that wrote output, so the task reports its result instead. A resume value alone does not mark a task finished, because it may pause again at its next interrupt. History and explicit checkpoint reads keep showing the interrupts as recorded. Fixes langchain-ai#3068 Authored by Mihir
🦋 Changeset detectedLatest commit: c66ae6d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@langchain/langgraph-checkpoint
@langchain/langgraph-checkpoint-mongodb
@langchain/langgraph-checkpoint-postgres
@langchain/langgraph-checkpoint-redis
@langchain/langgraph-checkpoint-sqlite
@langchain/langgraph-checkpoint-validation
create-langgraph
@langchain/langgraph-api
@langchain/langgraph-cli
@langchain/langgraph
@langchain/langgraph-cua
@langchain/langgraph-supervisor
@langchain/langgraph-swarm
@langchain/langgraph-ui
@langchain/langgraph-sdk
@langchain/angular
@langchain/react
@langchain/svelte
@langchain/vue
commit: |
Hide completed-task interrupts only in latest state, keep successive interrupts pending, and persist NO_WRITES for resumed tasks without output. Related: langchain-ai#3068, langchain-ai#3113 Prepared with AI assistance.
|
The sdk-vue failure appears to be a pre-existing test race: errorAgent can echo the submitted message before its node throws, making the correct optimistic status sent, while the test always expects failed. The separate fix (#3134) makes dispatch fail before any echo, as the React test already does, and adds deterministic tests for both event orders. The SDK stream suite passes locally (360 tests), along with SDK/Vue type checks and lint. Browser CI still needs to confirm the fix. |
Fixes #3068
Problem
Two parallel nodes call
interrupt(). Resuming one of them withCommand({ resume: { [id]: value } })writes its answer, and theinvoke()result lists only the other interrupt as pending.getState()still lists both, so an application that reads pending interrupts from the state (for example after a restart) asks the answered question again.The snapshot read the recorded
INTERRUPTwrite of every task, finished or not. The finished task was already left out ofnext, so its answered question showed up as pending with no task left to run.Change
finishedTaskIds(pendingWrites)inpregel/debug.ts: tasks that wrote output. Errors, interrupts, scheduling markers and a bare resume value do not count, because a resumed task may pause again at its nextinterrupt().tasksWithWritestakes an optional set of finished tasks and reports no interrupts for them, so theirresultis returned instead._prepareStateSnapshotpasses the set only when it applies pending writes, which is the latest-state read (getState()without acheckpoint_id). History and explicit-checkpoint reads show the interrupts as recorded, as before.@langchain/langgraph.Scope
The Python fix (langchain-ai/langgraph#9103) is wider: it also records
NO_WRITESwhen a resumed task finishes without output, and makesCommand(resume=value)without an id raise when several interrupts are pending. This PR does only thegetState()part. A task that was resumed and finished without writing anything still shows its answered interrupt, and I did not change the resume-by-id behavior. Happy to follow up on either if you want them.Tests
src/tests/state_pending_interrupts.test.ts:getState()lists only the pending interrupt,nextandtasksagree, and the finished task shows itsresultTwo of the four fail on the old code, and all four pass now.
libs/langgraph-core: 93 files, 2041 tests pass.tscandoxfmt --checkare clean for the files I changed.Authored by Mihir