P-1952 Handle race condition in wagmi and SDK initialization#160
P-1952 Handle race condition in wagmi and SDK initialization#160
Conversation
| /** | ||
| * Seed trackingState if wagmi is already in a connected state. | ||
| * This ensures transaction/signature events have an address available | ||
| * even when the SDK initializes after wagmi auto-reconnects. | ||
| */ | ||
| private initializeFromCurrentState(): void { | ||
| try { | ||
| const state = this.getState(); | ||
| if (state.status === "connected") { | ||
| const address = this.getConnectedAddress(state); | ||
| const chainId = state.chainId; | ||
| if (address) { | ||
| this.trackingState.lastAddress = address; | ||
| this.trackingState.lastChainId = chainId; | ||
| this.trackingState.lastStatus = "connected"; | ||
| logger.info( | ||
| "WagmiEventHandler: Wallet already connected, seeded tracking state", | ||
| { address, chainId } | ||
| ); | ||
| } | ||
| } | ||
| } catch (error) { | ||
| logger.error( | ||
| "WagmiEventHandler: Error reading initial state:", | ||
| error | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Missing test coverage for new method
The new initializeFromCurrentState() method has no corresponding tests. The existing test setup initializes the mock wagmi config in a disconnected state (line 70 of the test file), so the state.status === "connected" branch in this method is never exercised.
Consider adding tests for:
- Constructor seeds
trackingStatewhen wagmi is already connected at init time — verifyinglastAddress,lastChainId, andlastStatusare set. - Constructor handles errors from
getState()gracefully (doesn't throw). - Constructor handles the case where state is "connected" but
getConnectedAddressreturnsundefined(e.g., empty accounts).
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/wagmi/WagmiEventHandler.ts
Line: 130-157
Comment:
**Missing test coverage for new method**
The new `initializeFromCurrentState()` method has no corresponding tests. The existing test setup initializes the mock wagmi config in a `disconnected` state (line 70 of the test file), so the `state.status === "connected"` branch in this method is never exercised.
Consider adding tests for:
1. Constructor seeds `trackingState` when wagmi is already connected at init time — verifying `lastAddress`, `lastChainId`, and `lastStatus` are set.
2. Constructor handles errors from `getState()` gracefully (doesn't throw).
3. Constructor handles the case where state is "connected" but `getConnectedAddress` returns `undefined` (e.g., empty accounts).
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON, but it could not run because on-demand usage is turned off. To enable Bugbot Autofix, turn on on-demand usage and set a spend limit in the Cursor dashboard.
| if (address) { | ||
| this.trackingState.lastAddress = address; | ||
| this.trackingState.lastChainId = chainId; | ||
| this.trackingState.lastStatus = "connected"; |
There was a problem hiding this comment.
Missing chainId validation in initial state seeding
Medium Severity
initializeFromCurrentState only checks if (address) before seeding tracking state, but handleStatusChange uses a stricter guard: if (address && chainId !== undefined). Since WagmiState.chainId is typed number | undefined, the new method can seed lastAddress while lastChainId remains undefined — a partially-seeded state that the existing connect handler was explicitly designed to prevent.
Additional Locations (1)
Two possible causes:
<FormoAnalyticsProvider
For this user, it's almost certainly #1 since they see zero transaction events. If it were #2, they'd see transactions that happen after a manual reconnect but not on first page load. Zero transactions points to the mutation cache never being subscribed to at all. |


Note
Low Risk
Small, additive change limited to initialization logic; main risk is incorrect seeding if wagmi state access differs across wrappers, but it is guarded and logged.
Overview
Fixes a wagmi/SDK initialization race by seeding
WagmiEventHandlertracking state from the current wagmi connection state on startup, so analytics events haveaddress/chainIdeven when wagmi auto-reconnects before subscriptions are attached.Adds a new
initializeFromCurrentState()call in the constructor with guarded state reads and error logging; no changes to the existing subscription-based listeners beyond this startup initialization.Written by Cursor Bugbot for commit 9cdd857. This will update automatically on new commits. Configure here.
Greptile Summary
Fixes a race condition where wagmi auto-reconnects before the SDK's
subscribe()listeners are attached, leavingtrackingStatewithoutaddress/chainIdfor subsequent analytics events.initializeFromCurrentState()in theWagmiEventHandlerconstructor that synchronously reads the current wagmi connection state and seedstrackingStateif a wallet is already connected.setupConnectionListeners()to avoid any ordering issues.disconnectedstate at construction time, so the "already connected" branch is never exercised.Confidence Score: 4/5
Important Files Changed
initializeFromCurrentState()method to seed tracking state from current wagmi connection on startup, fixing a race condition where wagmi auto-reconnects before SDK subscriptions are attached. Change is well-guarded with try/catch and null checks, but lacks unit test coverage for the new code path.Sequence Diagram
sequenceDiagram participant App as App/Wagmi participant SDK as WagmiEventHandler participant State as wagmiConfig.getState() participant Track as trackingState Note over App,SDK: SDK initialization (constructor) App->>SDK: new WagmiEventHandler(formo, wagmiConfig) Note over SDK: NEW: initializeFromCurrentState() SDK->>State: getState() State-->>SDK: { status: "connected", chainId, connections } SDK->>SDK: getConnectedAddress(state) SDK->>Track: seed lastAddress, lastChainId, lastStatus Note over SDK: setupConnectionListeners() SDK->>App: wagmiConfig.subscribe(status) SDK->>App: wagmiConfig.subscribe(chainId) Note over App,Track: Later: transaction/signature events App->>SDK: mutation event (sendTransaction) SDK->>Track: read lastAddress, lastChainId Note over SDK: address/chainId available ✓Last reviewed commit: 9cdd857
Context used:
dashboard- Review and address all automated code review comments (like Copilot suggestions) before merging PRs,... (source)