issue: reports are failing #49
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Reports are failing with
"Failed to load report data"
Root cause identified and fix submitted
The
/api/reports/clientsendpoint crashes with a 500 because the churn risk query passes a JavaScriptDateobject into Drizzle ORM'ssqltemplate literal in aHAVINGclause. Thepostgresdriver cannot serializeDateobjects in this context — it throws:The other 4 report endpoints (summary, revenue, appointments, services) work fine — only the clients endpoint has this issue.
Fix: PR #50 converts the
Dateto an ISO string and adds a::timestamptzcast.Investigation
I reviewed the reports code end-to-end (
apps/api/src/routes/reports.ts,apps/web/src/pages/Reports.tsx, auth middleware, Drizzle schema, and migrations).The frontend throws "Failed to load report data" when any of the 5 API endpoints (
/summary,/revenue,/appointments,/services,/clients) returns a non-2xx response. The error gives no information about which one failed or why.The API route handlers have no error handling — if any Drizzle query or DB call throws, Hono returns an empty 500 that the frontend treats as a failure. Without access to the pod logs or the browser network tab, the specific cause can't be determined from code alone.
Fix
PR #51 adds:
reportsRouter.onError()— catches unhandled exceptions, logs them server-side, and returns a JSON{ error, message }500 so the cause is visible.clients (HTTP 500: relation "invoice_tip_splits" does not exist)).Once this is deployed, the next time reports fail, the error in the UI will identify the root cause directly.
To diagnose now (before the PR deploys)
If you can run
kubectl -n groombook logs -l app.kubernetes.io/name=api --tail=100, any DB or query errors will appear there as unhandled exceptions.Resolved — root cause confirmed and merged in PR #51.
Bug: The
/api/reports/clientsendpoint crashed with a 500 on every load. A raw JavaScriptDateobject was embedded in asqltemplate literal inside.having()in the churn-risk query.postgres-jscannot serialize aDatein this position — it threw a type error, the route handler crashed, and Hono returned an empty 500.Fix: Serialize the date as an ISO string with
::timestamptzcast so PostgreSQL handles it correctly. Also addedreportsRouter.onError()and improved the frontend error message for easier diagnosis of any future regressions.