This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry.
Project Overview
ReCode is a web-based AI code tool — conversion, analysis, and SQL/language transforms — built so people can just show up and use it without creating an account first. Under the hood, every visitor is authenticated anonymously through Firebase so their run history, per-tool drafts, and settings persist across sessions, and there's a 6-character code-based sync flow so someone can pick up an in-progress session on a second device.
Bug Fix or Performance Improvement
For about 5 months — since I first shipped the anonymous-auth and sync feature — the app had a bug that never threw a visible error, never showed up in any log I was watching, and quietly fragmented users' identities anyway.
Symptom: after leaving the app idle for a while (closing the tab, stepping away, letting a laptop sleep overnight), reopening it would sometimes show a brand new anonymous user. The old saved history was still sitting in Firestore — just unreachable, because the currently signed-in UID had silently changed underneath it. Local IndexedDB drafts, which don't key off the user at all, were always intact, which is actually what pointed me toward "this is an identity problem, not a storage problem."
By the time I went looking, my Firebase Auth console had 694 anonymous user accounts for an app with a tiny handful of real daily sessions.
There turned out to be two separate bugs stacked on top of each other:
1. A race condition in the client-side auth bootstrap. initializeAuth() registered a fresh onAuthStateChanged listener on every call and never unsubscribed. If it was called more than once before the first anonymous sign-in resolved — which happened routinely, since it's invoked both on app mount and lazily by the API client — each firing that still saw user === null kicked off its own signInAnonymously(). Two calls in quick succession meant two brand-new Firebase accounts, from a single visit.
2. A misconfigured GCP API key restriction. The bigger one. My Firebase browser API key had its allowed APIs deliberately locked down (good security practice) to Cloud Firestore, Identity Toolkit, and Gemini — but not Token Service API. Identity Toolkit covers sign-in itself, but refreshing an existing session is a separate call to securetoken.googleapis.com, and it was getting rejected with a flat 403 every time. The cached session worked fine short-term, but the moment the SDK actually needed to refresh it — exactly the "came back after being idle" case — the refresh silently failed, onAuthStateChanged reported no user, and my own code (reasonably, given what it could see) treated that as "nobody's signed in" and minted a fresh anonymous account.
Code
PR / commit: https://github.com/Georgel0/ReCode/commit/69511539d07793956c37abb57e9e49513ba98911
The race-condition fix, in lib/firebase/client.js:
+ let authReadyPromise = null;
export const initializeAuth = () => {
+ if (authReadyPromise) return authReadyPromise;
+
+ authReadyPromise = new Promise((resolve, reject) => {
- return new Promise((resolve, reject) => {
- onAuthStateChanged(auth, (user) => {
+ const unsubscribe = onAuthStateChanged(auth, (user) => {
+ unsubscribe(); // only ever resolve once per attempt
if (user) {
resolve(user);
} else {
signInAnonymously(auth)
.then(({ user }) => resolve(user))
- .catch((error) => {
- console.error("Auth Error:", error);
- reject(error);
- });
+ .catch((error) => {
+ console.error("Auth Error:", error);
+ authReadyPromise = null; // allow a retry on next call
+ reject(error);
+ });
}
});
});
+ return authReadyPromise;
};
The API-key fix wasn't a code change at all — it was adding Token Service API to the key's allowed API list, in Google Cloud Console → Credentials → API restrictions, alongside Firestore and Identity Toolkit.
My Improvements
Because the symptom was intermittent and two separate bugs were compounding, I worked through it by ruling out causes one at a time rather than guessing:
- Confirmed it wasn't React Strict Mode double-invoking effects in dev, since it reproduced in production too, where Strict Mode doesn't apply.
- Confirmed it wasn't Vercel's multiple preview/production domains, by checking the exact URL each time it happened.
- Confirmed it wasn't a dev-server port mismatch (Next.js silently bumping ports changes the browser origin, and therefore the IndexedDB scope).
- Confirmed it wasn't a browser privacy setting, a cookie-autodelete extension, or an incognito session.
- Confirmed it wasn't Firebase's own anonymous-account auto-cleanup — that setting wasn't even enabled on the project.
Once I logged every onAuthStateChanged transition and every signInAnonymously error code instead of swallowing them in a bare catch {}, the real cause showed up immediately in the network tab: a 403 from securetoken.googleapis.com. That's what led me to the API key restriction.
Fixing the root cause stops new orphans from being created, but it doesn't clean up the ones already there — so I also wrote a small Admin SDK script to bulk-delete the ~694 anonymous accounts that had piled up over 5 months, in batches of 1000 via listUsers/deleteUsers, explicitly excluding the UIDs I'm actively using.
The interesting lesson: locking an API key down to "only what the app calls" is good practice, but Firebase SDKs make calls on your behalf that never appear anywhere in your own code — token refresh being the obvious one in hindsight, invisible until you actually watch the network tab for long enough to see a session go stale.

Top comments (0)