From 7d01f1350029be187c05d7dd53f36dada9ed6328 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Wed, 22 Apr 2026 17:18:56 -0700 Subject: [PATCH] fix(orgtoken): cast org_id to text in COALESCE to prevent 500 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Symptom (prod tenant hongmingwang): GET /org/tokens → 500 orgtoken list: orgtoken: list: pq: invalid input syntax for type uuid: "" Postgres rejects COALESCE(uuid_col, '') because it can't cast the empty string to UUID. Cast to ::text first so the COALESCE operates on matching types. OrgID on the Go side is already string, so no scan changes needed. sqlmock doesn't exercise pq type coercion — it accepts any AddRow value for any column — which is why the existing tests pass while prod 500s. Real-Postgres integration coverage is the systemic fix (tracked separately), but this PR unblocks the Settings → Org Tokens page today. Co-Authored-By: Claude Opus 4.7 (1M context) --- workspace-server/internal/orgtoken/tokens.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/workspace-server/internal/orgtoken/tokens.go b/workspace-server/internal/orgtoken/tokens.go index 4276434c..94d588ec 100644 --- a/workspace-server/internal/orgtoken/tokens.go +++ b/workspace-server/internal/orgtoken/tokens.go @@ -142,8 +142,13 @@ func Validate(ctx context.Context, db *sql.DB, plaintext string) (id, prefix, or // symptom of abuse or a bug — the hard cap prevents one runaway // minting loop from O(N) pageloads in the admin UI. func List(ctx context.Context, db *sql.DB) ([]Token, error) { + // org_id is a UUID column — COALESCE must cast to text first, + // otherwise Postgres rejects the empty-string literal with + // "pq: invalid input syntax for type uuid: ''". sqlmock doesn't + // exercise pq type coercion, so this bug only surfaces against + // a real Postgres (prod). rows, err := db.QueryContext(ctx, ` - SELECT id, prefix, COALESCE(name,''), COALESCE(org_id,''), + SELECT id, prefix, COALESCE(name,''), COALESCE(org_id::text,''), COALESCE(created_by,''), created_at, last_used_at FROM org_api_tokens WHERE revoked_at IS NULL