1. The Incident
I was building Friday OS—my self-hosted, local-first AI Personal OS. The stack uses Firebase Realtime Database (RTDB) for real-time state syncing. I hit "Delete" on one of the log entries in my dashboard. The backend returned a clean 200 OK and Firebase Console updated immediately, but my React frontend went completely white. The console output showed:
TypeError: items.map is not a function
2. Root Cause: The Non-Existent Array
Firebase RTDB is a JSON tree. Under the hood, it has no native array type. When you write an array:
const agents = ["orchestrator", "fitness", "financial"];
Firebase stores it as an object with stringified integer keys:
{
"0": "orchestrator",
"1": "fitness",
"2": "financial"
}
If the keys are sequential integers starting at 0, the Firebase SDK automatically coerces the data back into a JavaScript array on read. But if you delete index 1 (fitness), the database state becomes:
{
"0": "orchestrator",
"2": "financial"
}
Because the sequence is broken, the SDK stops coercing and returns a raw JavaScript object. React expects an array to call .map(), receives an object instead, throws a TypeError, and crashes the screen.
3. The Code Fix: Defensive State Normalization
To prevent this, you must normalize your state where the Firebase snapshot enters your application:
// Defensive check to guarantee a true array
onValue(agentsRef, (snapshot) => {
const data = snapshot.val();
if (!data) {
setAgents([]);
} else if (Array.isArray(data)) {
setAgents(data);
} else {
// Sequence was broken, extract values from the coerced object
setAgents(Object.values(data));
}
});
Top comments (0)