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
Signed-in users are rendered as Anonymous on the comments and questions they author. The name is present in Firebase Auth but null in the Firestore users/{uid} document that the UI actually reads, so the || 'Anonymous' fallback fires.
Reproduced on the live site: a comment posted by a signed-in account whose Firebase Auth displayName is correctly set renders as "Anonymous", directly beneath older comments that render their author's name normally.
Evidence
Comparing Firebase Auth against the Firestore mirror for the same accounts:
Source
Value
Firebase Auth displayName
set correctly for every account
Firestore users/{uid}.displayName
null for 6 of 10 accounts
The Auth records all carry real names. The Firestore documents that the UI reads do not. Four accounts happen to have a correct displayName; the remaining six are null. One further account — the oldest, an admin — has no displayName at all and instead carries a legacy name field, matching the older schema also seen in #55.
Root cause: a race between onAuthStateChanged and signUp
src/contexts/AuthContext.tsx — signUp runs this sequence:
Step 1 signs the user in, which immediately fires the onAuthStateChanged observer registered earlier in the same file. That observer calls loadUserProfile(firebaseUser), which finds no Firestore document and creates one itself:
// AuthContext.tsx — inside loadUserProfileconstnewUserProfile: UserProfile={uid: firebaseUser.uid,email: firebaseUser.email,displayName: firebaseUser.displayName,// still null — step 2 has not run yetphotoURL: firebaseUser.photoURL,};awaitcreateUserProfile(newUserProfile);
firebaseUser.displayName is null at that instant, because updateProfile (step 2) has not executed. So the document is created with displayName: null.
Step 3 then attempts to write the correct value, but createUserProfile is guarded on non-existence:
The document now exists, so this is a silent no-op and the correct name is discarded. Whichever path wins the race determines whether the account has a name — which is why the outcome is split across existing accounts rather than uniformly broken.
Why a profile fix alone is not sufficient
Author details are denormalized into every question and comment at write time (questionService.addQuestion, commentService.addComment, eventService.addEvent all persist the whole author object — see #23). Content authored while displayName was null is permanently stamped with null; correcting the user document later does not retroactively fix existing posts.
A complete fix therefore has three parts:
Fix the race. Either set the Auth profile before the observer can create the document, or make createUserProfile fill in a missing displayName on an existing document instead of returning early. The second is more robust, since it repairs the state regardless of ordering.
Backfill users/{uid}.displayName from Firebase Auth. The correct values already exist in the Auth records, so this is a straightforward one-off script over listUsers().
Backfill the denormalized author.displayName on existing questions, events, and questions/{id}/comments documents — or implement Stop denormalizing full UserProfile into question/comment/event docs #23 (store an author reference and resolve display fields at read time), which repairs all history at once and prevents the class of problem recurring.
Also worth trimming input on the way in: at least one Auth record has a trailing space in its displayName, so the sign-up form is not trimming.
Signed-in users are rendered as Anonymous on the comments and questions they author. The name is present in Firebase Auth but
nullin the Firestoreusers/{uid}document that the UI actually reads, so the|| 'Anonymous'fallback fires.Reproduced on the live site: a comment posted by a signed-in account whose Firebase Auth
displayNameis correctly set renders as "Anonymous", directly beneath older comments that render their author's name normally.Evidence
Comparing Firebase Auth against the Firestore mirror for the same accounts:
displayNameusers/{uid}.displayNamenullfor 6 of 10 accountsThe Auth records all carry real names. The Firestore documents that the UI reads do not. Four accounts happen to have a correct
displayName; the remaining six arenull. One further account — the oldest, an admin — has nodisplayNameat all and instead carries a legacynamefield, matching the older schema also seen in #55.Root cause: a race between
onAuthStateChangedandsignUpsrc/contexts/AuthContext.tsx—signUpruns this sequence:Step 1 signs the user in, which immediately fires the
onAuthStateChangedobserver registered earlier in the same file. That observer callsloadUserProfile(firebaseUser), which finds no Firestore document and creates one itself:firebaseUser.displayNameisnullat that instant, becauseupdateProfile(step 2) has not executed. So the document is created withdisplayName: null.Step 3 then attempts to write the correct value, but
createUserProfileis guarded on non-existence:The document now exists, so this is a silent no-op and the correct name is discarded. Whichever path wins the race determines whether the account has a name — which is why the outcome is split across existing accounts rather than uniformly broken.
Why a profile fix alone is not sufficient
Author details are denormalized into every question and comment at write time (
questionService.addQuestion,commentService.addComment,eventService.addEventall persist the wholeauthorobject — see #23). Content authored whiledisplayNamewasnullis permanently stamped withnull; correcting the user document later does not retroactively fix existing posts.A complete fix therefore has three parts:
createUserProfilefill in a missingdisplayNameon an existing document instead of returning early. The second is more robust, since it repairs the state regardless of ordering.users/{uid}.displayNamefrom Firebase Auth. The correct values already exist in the Auth records, so this is a straightforward one-off script overlistUsers().author.displayNameon existingquestions,events, andquestions/{id}/commentsdocuments — or implement Stop denormalizing full UserProfile into question/comment/event docs #23 (store an author reference and resolve display fields at read time), which repairs all history at once and prevents the class of problem recurring.Also worth trimming input on the way in: at least one Auth record has a trailing space in its
displayName, so the sign-up form is not trimming.Notes
doc.existscorrectly (property rather than method) in every service module, and the affected accounts date back to June 2025.nameschema on the oldest account).src/components/qna/ThreadedCommentCard.tsx,src/components/qna/CommentCard.tsx,src/components/qna/QuestionList.tsx,src/app/qna/[id]/page.tsx,src/app/page.tsx.