fix(graph): avoid duplicate state in compiled subgraphs - #4823
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 85b9a8a291
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| context.mergeIntoCurrentState(partialStateWithoutFlux); | ||
| context.mergeIntoCurrentState(updateState); | ||
| if (context.getNodeAction(context.getCurrentNodeId()) instanceof SubCompiledGraphNodeAction) { | ||
| context.replaceCurrentState(updateState); |
There was a problem hiding this comment.
Don’t replace parent state after subgraph errors
When a compiled subgraph’s embedded Flux ends with a GraphResponse.error (for example, a child node throws and the parent is consumed via graphResponseStream), nodeResultValue is empty so updateState remains empty. This new branch then calls replaceCurrentState(updateState), which resets the parent state to an empty snapshot and continues routing/checkpointing; the previous merge path was a no-op for an empty update. Skip replacement when the last subgraph response is an error, or only replace after a final map result is present.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in 2a0b261e3. Compiled-subgraph snapshot replacement is explicitly gated on both a state-map result and a non-error response, so an error cannot clear the parent state. The regression test now also routes conditionally after the child error and verifies that the preserved parent state selects the recovery branch. SubGraphTest passes 14/14, and the graph-core suite passes 405 tests with 71 environment-dependent skips; Checkstyle and Spotless are clean.
2a0b261 to
56689a9
Compare
Summary
APPENDkey and for subgraph error handlingRoot cause
A compiled subgraph starts with the parent's full state and returns its full final state. The parent executor then merged that result as a delta, so
APPENDre-added all inherited values after every subgraph completion.The snapshot replacement must only run after a successful final map result. Error responses do not contain a state result and must leave the existing parent state unchanged.
Impact
Nested compiled subgraphs no longer duplicate inherited list entries, and subgraph errors no longer clear the parent state. Ordinary embedded Flux nodes keep their existing incremental merge behavior.
Validation
./mvnw -pl :spring-ai-alibaba-graph-core -Dtest=SubGraphTest,CompiledSubGraphTest,StateGraphTest test(53 tests, 0 failures/errors, 1 skipped)./mvnw -pl :spring-ai-alibaba-graph-core -Dtest=*,!DatabaseStorePostgreSqlIntegrationTest test(399 tests, 0 failures/errors, 71 environment-dependent skips)The excluded PostgreSQL integration test requires a running Docker environment.
Fixes #4305