[object Object]

← back to Govarbitrage

TK-11464 fix (re-commit): gate orderBy nulls-ordering to nullable sort columns only

c62e15366045dd62f358658bff6feaa75919eff9 · 2026-09-12 07:24:46 -0700 · Steve Abrams

Re-commit — the prior fix commit was lost when this repo's .git was reset by
an external process on the re-populated tree. The working-tree fix was intact.
Sort-by-title (and any required native column) 500'd with PrismaClientValidationError
because the {sort,nulls} orderBy object form was applied to required fields;
Prisma only accepts it on nullable fields. Gate behind NULLABLE_NATIVE_SORT_COLUMNS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UYTNq3N4J57Gcna8XdPJ18

Files touched

Diff

commit c62e15366045dd62f358658bff6feaa75919eff9
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sat Sep 12 07:24:46 2026 -0700

    TK-11464 fix (re-commit): gate orderBy nulls-ordering to nullable sort columns only
    
    Re-commit — the prior fix commit was lost when this repo's .git was reset by
    an external process on the re-populated tree. The working-tree fix was intact.
    Sort-by-title (and any required native column) 500'd with PrismaClientValidationError
    because the {sort,nulls} orderBy object form was applied to required fields;
    Prisma only accepts it on nullable fields. Gate behind NULLABLE_NATIVE_SORT_COLUMNS.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01UYTNq3N4J57Gcna8XdPJ18
---
 src/lib/listings.ts | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/lib/listings.ts b/src/lib/listings.ts
index f7a30dd..c0d826b 100644
--- a/src/lib/listings.ts
+++ b/src/lib/listings.ts
@@ -150,6 +150,13 @@ const NATIVE_SORT_COLUMNS = new Set<keyof ListingRow>([
   "researchStatus",
 ]);
 
+const NULLABLE_NATIVE_SORT_COLUMNS = new Set<keyof ListingRow>([
+  "closingAt",
+  "category",
+  "manufacturer",
+  "model",
+]);
+
 export async function queryListings(params: QueryParams) {
   const {
     search,
@@ -197,7 +204,11 @@ export async function queryListings(params: QueryParams) {
         include: { research: true, costBreakdown: true, scores: true },
         // nulls first on asc / last on desc mirrors the JS fallback's
         // String(v ?? "") ordering, so the DB path is order-equivalent.
-        orderBy: { [sort]: { sort: dir, nulls: dir === "asc" ? "first" : "last" } } as Prisma.ListingOrderByWithRelationInput,
+        orderBy: {
+          [sort]: NULLABLE_NATIVE_SORT_COLUMNS.has(sort)
+            ? { sort: dir, nulls: dir === "asc" ? "first" : "last" }
+            : dir,
+        } as Prisma.ListingOrderByWithRelationInput,
         skip: (page - 1) * pageSize,
         take: pageSize,
       }),

← 6531e6f TK-11464 test: regression guard for sort orderBy nullability  ·  back to Govarbitrage  ·  Snapshot: commit staged govarbitrage scaffold (Docker, READM 5c6b0bb →