From b3f7e6006e19eb56bc030c6b0f6aaa87e9d9ab63 Mon Sep 17 00:00:00 2001 From: John Knapp Date: Fri, 12 Jun 2026 11:46:44 -0700 Subject: [PATCH] fix: snippet.list tag filter (same array-binding bug as memory.list) (#1) Replace the raw `${snippets.tags} @> ${tags}::text[]` template with Drizzle's arrayContains, matching the memory.list fix. The raw template expanded the JS array into positional params, producing a malformed array literal (one tag) / record-cast error (two tags) at runtime. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/web/lib/snippets.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/web/lib/snippets.ts b/apps/web/lib/snippets.ts index 668aab8..4fba1a7 100644 --- a/apps/web/lib/snippets.ts +++ b/apps/web/lib/snippets.ts @@ -1,4 +1,4 @@ -import { and, desc, eq, inArray, isNull, or, sql } from "drizzle-orm"; +import { and, arrayContains, desc, eq, inArray, isNull, or } from "drizzle-orm"; import { db } from "@/lib/db/client"; import { snippets, projects } from "@/lib/db/schema"; import type { Snippet } from "@/lib/db/schema"; @@ -349,7 +349,13 @@ export async function listSnippets( } if (tags && tags.length > 0) { - where.push(sql`${snippets.tags} @> ${tags}::text[]`); + // Require ALL listed tags (array containment). Use Drizzle's + // arrayContains so the JS array binds as a single text[] param + // (via the column's toDriver) rather than being expanded into + // positional params — a raw `${tags}::text[]` template expands to + // `($1)::text[]` / `($1,$2)::text[]`, which Postgres rejects as a + // malformed array literal / record cast. + where.push(arrayContains(snippets.tags, tags)); } const rows = await db