Fix reports crash on client churn risk query #50

Merged
ghost merged 1 commits from fix/reports-clients-churn-query into main 2026-03-18 13:26:26 +00:00
ghost commented 2026-03-18 13:23:55 +00:00 (Migrated from github.com)

Summary

  • Fix /api/reports/clients endpoint returning 500 Internal Server Error
  • Root cause: Drizzle ORM's sql template literal in a HAVING clause cannot serialize a JavaScript Date object — the postgres driver throws "The string argument must be of type string or an instance of Buffer"
  • Fix: convert the Date to an ISO string and add an explicit ::timestamptz cast

Root cause analysis

The churn risk query passes a Date object directly into a Drizzle sql tagged template:

.having(sql`MAX(...) < ${ninetyDaysAgo} OR ...`)

While Drizzle handles Date parameters in .where() clauses (via its column-aware type system), raw sql template parameters in .having() are passed directly to the postgres driver which cannot serialize Date objects in this context.

Test plan

  • Reproduced locally: raw SQL works, Drizzle having() with Date throws
  • Verified fix: converting to ISO string + ::timestamptz cast resolves the error
  • Full endpoint simulation passes (all 3 sub-queries return data)
  • TypeScript type-check passes
  • CI passes

Closes #49

🤖 Generated with Claude Code

## Summary - Fix `/api/reports/clients` endpoint returning 500 Internal Server Error - Root cause: Drizzle ORM's `sql` template literal in a `HAVING` clause cannot serialize a JavaScript `Date` object — the `postgres` driver throws "The string argument must be of type string or an instance of Buffer" - Fix: convert the `Date` to an ISO string and add an explicit `::timestamptz` cast ## Root cause analysis The churn risk query passes a `Date` object directly into a Drizzle `sql` tagged template: ```ts .having(sql`MAX(...) < ${ninetyDaysAgo} OR ...`) ``` While Drizzle handles `Date` parameters in `.where()` clauses (via its column-aware type system), raw `sql` template parameters in `.having()` are passed directly to the `postgres` driver which cannot serialize `Date` objects in this context. ## Test plan - [x] Reproduced locally: raw SQL works, Drizzle `having()` with `Date` throws - [x] Verified fix: converting to ISO string + `::timestamptz` cast resolves the error - [x] Full endpoint simulation passes (all 3 sub-queries return data) - [x] TypeScript type-check passes - [ ] CI passes Closes #49 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This repo is archived. You cannot comment on pull requests.