Fix race conditions in AI function call processing#8369
Merged
4ian merged 4 commits intoclaude/upgrade-react-18-6oNEDfrom Mar 10, 2026
Merged
Fix race conditions in AI function call processing#83694ian merged 4 commits intoclaude/upgrade-react-18-6oNEDfrom
4ian merged 4 commits intoclaude/upgrade-react-18-6oNEDfrom
Conversation
…ent back
Two fixes for a bug where the AI conversation gets stuck after processing
function calls (especially in orchestrator mode), directly related to the
React 18 upgrade:
1. Use a ref as source of truth for editor function call results
(AiRequestContext.js): getEditorFunctionCallResults previously read from
React state, which is subject to React 18 automatic batching. After
calling addEditorFunctionCallResults('working'), the state update was
deferred, so subsequent reads returned stale data without 'working'
markers. Now uses a ref for synchronous reads with forceUpdate() for
UI re-renders.
2. Add in-flight guard against duplicate function call processing
(Utils.js): Defense-in-depth ref-based set that prevents concurrent
processing of the same call_id, covering React 18 StrictMode
double-invocations and any remaining re-entrancy edge cases.
In React 17, setState in async callbacks was synchronous, so 'working'
markers were visible immediately and prevented re-firing. React 18 batches
these updates, which could cause the processing effect to re-fire before
the markers were visible.
https://claude.ai/code/session_019BRFfuhnwRNmHJyk429KWm
Add console.info/error at key decision points where the send or processing flow can silently bail out, to make future debugging easier: - onSendMessage: log when blocked by isSendingAiRequest, hasUnfinishedResult, or hasFunctionsCallsToProcess guards - onSendMessage catch: log the error before storing it - onProcessFunctionCalls: log when skipped by in-flight guard or when results are discarded due to suspension/abort https://claude.ai/code/session_019BRFfuhnwRNmHJyk429KWm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR fixes race conditions in the AI generation system that could cause duplicate function call processing and stuck "sending" states. The changes add proper synchronization guards and improve error handling to prevent concurrent processing of the same function calls.
Key Changes
Added re-entrancy guard in
useProcessFunctionCalls: Introduced aprocessingCallIdsRefto track function calls currently being processed, preventing the same call from being processed multiple times due to React 18's automatic batching behavior. The guard is cleaned up in afinallyblock to allow retries if needed.Wrapped function call processing in try-finally: Ensures cleanup of the processing guard even if an error occurs during function call execution.
Improved send state management in
AskAiEditor:isSendingAiRequestcheck into its own conditional block with informative loggingsetSendingAiRequest(false)was not called in the error handler, which could leave the UI in a stuck "sending" stateImplementation Details
The race condition occurred because React 18's automatic batching defers state updates. When
addEditorFunctionCallResults('working')was called, the state update was deferred, allowing the effect to re-fire before the 'working' state became visible. This caused the same function calls to be processed multiple times.The solution uses a ref-based set to track call IDs currently being processed, which is synchronous and not affected by batching. The guard filters out any calls already in progress and cleans them up after processing completes (or fails).
The error handling fix ensures that if sending fails, the UI properly resets the sending state so users can retry.
https://claude.ai/code/session_019BRFfuhnwRNmHJyk429KWm