Fixing the “D.map is not a function” crash by tightening DB indexes and normalizing the API payload TL;DR: I added missing PostgreSQL indexes in and forced the endpoint to always return an array.
The change stopped the runtime in the React selector and restored correct KPI calculations.
The Problem Our internal “Condo Dashboard” started throwing a JavaScript error in production: is the data array used to populate a with condo options.
When the page loaded, the dropdown was empty and the whole component crashed.
The API call that feeds () was supposed to return an array of objects , but under certain conditions it returned or a single object, breaking the call.
The root cause turned out to be duplicate rows in the table that caused the query to return a malformed result set.
Those duplicates were a side‑effect of missing unique indexes on the and tables.
What I Tried First Guarding the Front‑end – I added a quick check in : This silenced the error, but the UI still showed no options because the API kept returning the wrong shape.
It was a band‑aid, not a fix.
Manual Data Normalization – In the API controller I forced the result to an array: This produced duplicate entries and confused downstream calculations.
The KPI numbers in the dashboard were still off.
Both approaches addressed the symptom but left the database inconsistency untouched, so the bug could re‑appear anytime new data landed.
The Implementation
1.
Add proper indexes (the real fix) The missing indexes allowed duplicate rows for the same and .
I added them in .
Below is the diff that went into the repository (commit 7a6ca68e): Why these indexes? guarantees a single token per broker, eliminating the duplicate rows that broke the metrics aggregation. speeds up the join that builds the selector payload, reducing the chance of timeouts that previously left the query partially resolved (hence ).
The foreign key makes the schema self‑healing: orphaned metric rows are automatically removed.
2.
Refactor the metrics endpoint to enforce array output With the DB clean, I tightened the controller () to guarantee an array:
3.
Small front‑end sanity check (still useful) I left a minimal guard in to avoid future crashes if the API ever misbehaves again:
4.
Update documentation and changelog I recorded the change in : The changelog now reflects the exact lines added, making future audits straightforward.
Key Takeaway Database schema gaps (missing unique indexes or foreign keys) can surface as seemingly unrelated front‑end bugs.
Always verify that the data contract you rely on is enforced at the source; a single duplicate row can turn an array into a scalar and break calls.
Adding proper indexes not only fixes the immediate bug but also improves query performance and data hygiene.
What's Next Write integration tests for that assert the response is always an array, even when the table is empty.
Add a migration script () so the indexes are version‑controlled and can be applied to staging/production automatically.
Instrument the API with a Prometheus metric Part of my Build in Public series — sharing the real process of building SaaS projects from Playa del Carmen, México.
Repo: · 2026-08-31 #playadev #buildinpublic