← back to Commercialrealestate
graceful-degrade /api/leads/frank + /api/broker (502 -> 200 when cre DB absent)
cb778e729ec546dd94067d09babb8fcbfc883e59 · 2026-07-16 17:54:46 -0700 · Steve
On prod (Kamatera) the broker DB module loads but there's no 'cre' Postgres,
so pool.query throws and both endpoints hard-502'd -> red console errors on
every internal page load. Return the front-end-safe shapes at 200 instead:
leads:[]+unavailable (panel already shows 'no leads (broker DB unavailable)'),
and the same {error} body (modal handles d.error; featured card guards !d.broker).
Verified by reproducing the prod condition (brokerdb loaded, DB unreachable):
both now 200; working-DB success path untouched.
Files touched
Diff
commit cb778e729ec546dd94067d09babb8fcbfc883e59
Author: Steve <steve@designerwallcoverings.com>
Date: Thu Jul 16 17:54:46 2026 -0700
graceful-degrade /api/leads/frank + /api/broker (502 -> 200 when cre DB absent)
On prod (Kamatera) the broker DB module loads but there's no 'cre' Postgres,
so pool.query throws and both endpoints hard-502'd -> red console errors on
every internal page load. Return the front-end-safe shapes at 200 instead:
leads:[]+unavailable (panel already shows 'no leads (broker DB unavailable)'),
and the same {error} body (modal handles d.error; featured card guards !d.broker).
Verified by reproducing the prod condition (brokerdb loaded, DB unreachable):
both now 200; working-DB success path untouched.
---
scripts/serve.js | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/scripts/serve.js b/scripts/serve.js
index ee3646b..bee3d33 100644
--- a/scripts/serve.js
+++ b/scripts/serve.js
@@ -320,7 +320,11 @@ app.get('/api/leads/frank', async (req, res) => {
FROM ll GROUP BY broker_id, name, firm, agent_type
ORDER BY fit_score DESC, total_value DESC LIMIT $1`, [limit])).rows;
res.json({ leads, scoredBy: 'Arcstone-financeability of current listings (mixed-use/condo×3, multifamily/commercial×2). Business data; no owner names.' });
- } catch (e) { res.status(502).json({ error: String(e.message).split('\n')[0], leads: [] }); }
+ } catch (e) {
+ // Graceful degrade (prod has no `cre` Postgres → pool.query throws): the front-end iterates
+ // d.leads, so an empty-array 200 renders "no leads" cleanly instead of a 502 console error.
+ res.json({ leads: [], unavailable: true, reason: String(e.message).split('\n')[0] });
+ }
});
// Licensed agents/brokers — every RE agent CRCP harvested, backed by a REAL California DRE
@@ -708,7 +712,12 @@ app.get('/api/broker', async (req, res) => {
compsNote: comps.length ? 'Recent sold comps in this broker’s areas (Redfin) with sold dates + MLS# — area context, not this broker’s own closings.' : null,
expiredNote: expired.length ? 'Listings of this broker that now appear in the sold feed (best-effort address match).' : 'No off-market/expired feed yet — none of this broker’s listings matched a sold record.',
closedNote: closed.length ? null : 'Per-broker closed history needs a gated detail-scrape; area sales shown instead.' });
- } catch (e) { res.status(502).json({ error: String(e.message).split('\n')[0] }); }
+ } catch (e) {
+ // Graceful degrade (prod has no `cre` Postgres → pool.query throws): SAME {error} body the
+ // front-end already handles (modal shows d.error; featured card guards !d.broker), but 200 not
+ // 502 so it isn't a red console error on every internal page load.
+ res.json({ error: String(e.message).split('\n')[0], unavailable: true });
+ }
});
// Firm detail — the roster (brokers/agents at the firm) + aggregate listings. Powers the click-through
← b4b3c10 add CRCP origin-vs-live drift canary (DTD verdict D)
·
back to Commercialrealestate
·
CRCP list view: sortable + fully hrefd rows, inline row expa 123b0e3 →