[object Object]

← back to Nineoh Guide

5x sweep 1: fix /api/cast 500 — credits has no show_id; scope by characters.show_id

dc8c199a9ecdd197497e4a2f7af992111d1ce847 · 2026-09-12 20:34:04 -0700 · Steve Abrams

The /api/cast route referenced cr.show_id (credits.show_id), which does not
exist in the schema — only characters.show_id carries show scoping. Postgres
threw 'column cr.show_id does not exist', the route caught it and returned
{cast:[]} with HTTP 500, so the Expo app got an empty cast list. Replaced the
coalesce(cr.show_id, ch.show_id) with ch.show_id in the select, distinct-on,
and order-by. /api/cast now returns 200 with populated showId.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit dc8c199a9ecdd197497e4a2f7af992111d1ce847
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sat Sep 12 20:34:04 2026 -0700

    5x sweep 1: fix /api/cast 500 — credits has no show_id; scope by characters.show_id
    
    The /api/cast route referenced cr.show_id (credits.show_id), which does not
    exist in the schema — only characters.show_id carries show scoping. Postgres
    threw 'column cr.show_id does not exist', the route caught it and returned
    {cast:[]} with HTTP 500, so the Expo app got an empty cast list. Replaced the
    coalesce(cr.show_id, ch.show_id) with ch.show_id in the select, distinct-on,
    and order-by. /api/cast now returns 200 with populated showId.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 apps/web/app/api/cast/route.ts | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/apps/web/app/api/cast/route.ts b/apps/web/app/api/cast/route.ts
index f440acf..f741bdf 100644
--- a/apps/web/app/api/cast/route.ts
+++ b/apps/web/app/api/cast/route.ts
@@ -11,11 +11,11 @@ export async function GET() {
   try {
     // Main cast + recurring/guest stars, scoped PER SHOW. A person may appear
     // in BOTH shows, so we emit one row per (person, show) — the client filters
-    // by the selected show's id. show_id comes from the credit (main-cast rows
-    // set credits.show_id) or, failing that, the character's show (recurring).
+    // by the selected show's id. show_id comes from the credited character's
+    // show (credits carries no show_id of its own; characters.show_id does).
     const { rows } = await pool.query(
-      `select distinct on (cp.id, coalesce(cr.show_id, ch.show_id))
-              cp.id, coalesce(cr.show_id, ch.show_id) as show_id,
+      `select distinct on (cp.id, ch.show_id)
+              cp.id, ch.show_id as show_id,
               cp.name, cp.biography_original,
               ch.name as character_name, cr.credit_type as kind, cr.billing_order,
               a.file_url, a.attribution_text, a.license_type, a.license_url
@@ -24,7 +24,7 @@ export async function GET() {
               and cr.credit_type in ('main-cast','recurring')
          left join characters ch on ch.id = cr.character_id
          left join assets a on a.id = cp.headshot_asset_id
-        order by cp.id, coalesce(cr.show_id, ch.show_id),
+        order by cp.id, ch.show_id,
                  (cr.credit_type = 'main-cast') desc nulls last,
                  cr.billing_order nulls last`
     );

← 8d5fd18 eas: pin production ios.image=latest (ITMS-90725 guard) befo  ·  back to Nineoh Guide  ·  5x: verification report — 3 sweeps, /api/cast 500 fixed, cle 6693593 →