From d362479bd330adeb3eff09203398b8761ae5027c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 11:53:30 +0000 Subject: [PATCH 1/4] Initial plan From 8aeaf9a46d0c41f18073296b1c5d26c55ff2bdab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 11:56:24 +0000 Subject: [PATCH 2/4] Fix COALESCE query to handle NULL values when column doesn't exist The previous query `COALESCE((to_jsonb(apps) ->> 'allow_device_custom_id')::boolean, true)` would fail when the column doesn't exist because: 1. to_jsonb(apps) ->> 'allow_device_custom_id' returns NULL (as text) 2. NULL::text cast to ::boolean fails with an error 3. COALESCE never gets a chance to provide the default The fix: `COALESCE(to_jsonb(apps) ->> 'allow_device_custom_id', 'true')::boolean` 1. Provide the default 'true' string BEFORE the boolean cast 2. COALESCE returns either the column value or 'true' as text 3. Cast the resulting text to boolean Co-authored-by: riderx <4084527+riderx@users.noreply.github.com> --- supabase/functions/_backend/plugins/stats.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/supabase/functions/_backend/plugins/stats.ts b/supabase/functions/_backend/plugins/stats.ts index 5faedace3f..e5eb56c25e 100644 --- a/supabase/functions/_backend/plugins/stats.ts +++ b/supabase/functions/_backend/plugins/stats.ts @@ -26,7 +26,8 @@ async function allowDeviceCustomIdFromPg(drizzleClient: ReturnType>... so the // query still parses even if the column doesn't exist yet. - allow_device_custom_id: sql`COALESCE((to_jsonb(apps) ->> 'allow_device_custom_id')::boolean, true)`, + // Default to 'true' before casting to boolean to handle NULL values when column doesn't exist + allow_device_custom_id: sql`COALESCE(to_jsonb(apps) ->> 'allow_device_custom_id', 'true')::boolean`, }) .from(schema.apps) .where(eq(schema.apps.app_id, app_id)) From dc796bff8cf7232910c087d67ee415cf50331e60 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 11:57:01 +0000 Subject: [PATCH 3/4] Fix has_usage_credits COALESCE query with same issue Applied the same fix to the has_usage_credits query in pg.ts to prevent potential failures when the column doesn't exist on replicas. Co-authored-by: riderx <4084527+riderx@users.noreply.github.com> --- supabase/functions/_backend/utils/pg.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/supabase/functions/_backend/utils/pg.ts b/supabase/functions/_backend/utils/pg.ts index 89f4dabd6d..bbd00b7103 100644 --- a/supabase/functions/_backend/utils/pg.ts +++ b/supabase/functions/_backend/utils/pg.ts @@ -51,7 +51,7 @@ function buildPlanValidationExpression( SELECT 1 FROM ${schema.orgs} WHERE ${schema.orgs.id} = ${ownerColumn} - AND COALESCE((to_jsonb(orgs) ->> 'has_usage_credits')::boolean, false) = true + AND COALESCE(to_jsonb(orgs) ->> 'has_usage_credits', 'false')::boolean = true )` return sql`(${hasCreditsExpression}) OR EXISTS ( SELECT 1 From af6c3620cecefa44214c2c03a9e85bf1fbe0df03 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 12:01:51 +0000 Subject: [PATCH 4/4] Simplify allow_device_custom_id query - remove unnecessary COALESCE Since the column is NOT NULL DEFAULT true, we can query it directly without the to_jsonb workaround. Reverted pg.ts change as well since that was based on the same incorrect assumption. Co-authored-by: riderx <4084527+riderx@users.noreply.github.com> --- supabase/functions/_backend/plugins/stats.ts | 7 ++----- supabase/functions/_backend/utils/pg.ts | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/supabase/functions/_backend/plugins/stats.ts b/supabase/functions/_backend/plugins/stats.ts index e5eb56c25e..3efbf24fd7 100644 --- a/supabase/functions/_backend/plugins/stats.ts +++ b/supabase/functions/_backend/plugins/stats.ts @@ -3,7 +3,7 @@ import type { MiddlewareKeyVariables } from '../utils/hono.ts' import type { Database } from '../utils/supabase.types.ts' import type { AppStats, StatsActions } from '../utils/types.ts' import { greaterOrEqual, parse } from '@std/semver' -import { eq, sql } from 'drizzle-orm' +import { eq } from 'drizzle-orm' import { Hono } from 'hono/tiny' import { z } from 'zod/mini' import { getAppStatus, setAppStatus } from '../utils/appStatus.ts' @@ -24,10 +24,7 @@ const PLAN_ERROR = 'Cannot send stats, upgrade plan to continue to update' async function allowDeviceCustomIdFromPg(drizzleClient: ReturnType, app_id: string): Promise { const res = await drizzleClient .select({ - // Replicas may lag schema changes. Read via to_jsonb(row)->>... so the - // query still parses even if the column doesn't exist yet. - // Default to 'true' before casting to boolean to handle NULL values when column doesn't exist - allow_device_custom_id: sql`COALESCE(to_jsonb(apps) ->> 'allow_device_custom_id', 'true')::boolean`, + allow_device_custom_id: schema.apps.allow_device_custom_id, }) .from(schema.apps) .where(eq(schema.apps.app_id, app_id)) diff --git a/supabase/functions/_backend/utils/pg.ts b/supabase/functions/_backend/utils/pg.ts index bbd00b7103..89f4dabd6d 100644 --- a/supabase/functions/_backend/utils/pg.ts +++ b/supabase/functions/_backend/utils/pg.ts @@ -51,7 +51,7 @@ function buildPlanValidationExpression( SELECT 1 FROM ${schema.orgs} WHERE ${schema.orgs.id} = ${ownerColumn} - AND COALESCE(to_jsonb(orgs) ->> 'has_usage_credits', 'false')::boolean = true + AND COALESCE((to_jsonb(orgs) ->> 'has_usage_credits')::boolean, false) = true )` return sql`(${hasCreditsExpression}) OR EXISTS ( SELECT 1