You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
getSnapshot() returns observable.immutableStatus, which is SuspenseSubject._immutableStatus — a single shared object reference for all components using the same observableId. Mutating it in-place means one component's render corrupts the snapshot for every other component sharing that observable.
Concrete failure scenario
Two components both call useUser() for the same auth instance (same observableId → same SuspenseSubject → same _immutableStatus object):
Component B calls getSnapshot() — it gets the same already-mutated object and renders status: 'success' with a user, even though it passed no initialData and the observable hasn't emitted yet.
useSyncExternalStore's tearing detection does not catch this: Object.is() on the same reference always returns true, so React treats the store as unchanged.
_updateImmutableStatus() (called on each observable emission) creates a new object — so the mutation is eventually overwritten. But between mount and first emission, the shared snapshot is wrong.
Why this surfaced now
This was a pre-existing bug, but it was only triggered when callers explicitly passed initialData. PR #731 seeds initialData from auth.currentUser on every mount of a signed-in user, making this path hit far more frequently.
Activity
fix: return new object from initialData path instead of mutating shar…
fix: return new object from initialData path instead of mutating shar…
fix: seed useUser with auth.currentUser to prevent undefined on initi…