From df62c9271a2257d51ffa94c2618b738cc416f724 Mon Sep 17 00:00:00 2001 From: John Brahy Date: Mon, 20 Apr 2026 21:26:57 -0700 Subject: [PATCH] Handle defensive ALTER TABLE defects in migrations The defensive ADD COLUMN statements in migrations 020, 025, and 027 use Effect.catch to swallow "duplicate column" errors on re-runs, but @effect/sql-sqlite-bun throws from db.query() outside its try/catch, so the SQLiteError surfaces as an Effect defect rather than a failure. Effect.catch only handles failures, so migration 27 crashed on fresh databases because migration 25 had already added default_model_selection. Switch to Effect.catchCause so both failures and defects are absorbed. --- .../persistence/Migrations/020_SmeConversationProviderAuth.ts | 4 ++-- .../persistence/Migrations/025_CanonicalizeModelSelections.ts | 4 ++-- .../persistence/Migrations/025_ProjectionProjectIconPath.ts | 2 +- .../Migrations/027_CanonicalizeModelSelectionsBackfill.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/server/src/persistence/Migrations/020_SmeConversationProviderAuth.ts b/apps/server/src/persistence/Migrations/020_SmeConversationProviderAuth.ts index 192705fe5..9c3ee26fb 100644 --- a/apps/server/src/persistence/Migrations/020_SmeConversationProviderAuth.ts +++ b/apps/server/src/persistence/Migrations/020_SmeConversationProviderAuth.ts @@ -7,12 +7,12 @@ export default Effect.gen(function* () { yield* sql` ALTER TABLE sme_conversations ADD COLUMN provider TEXT NOT NULL DEFAULT 'claudeAgent' - `.pipe(Effect.catch(() => Effect.void)); + `.pipe(Effect.catchCause(() => Effect.void)); yield* sql` ALTER TABLE sme_conversations ADD COLUMN auth_method TEXT NOT NULL DEFAULT 'auto' - `.pipe(Effect.catch(() => Effect.void)); + `.pipe(Effect.catchCause(() => Effect.void)); yield* sql` UPDATE sme_conversations diff --git a/apps/server/src/persistence/Migrations/025_CanonicalizeModelSelections.ts b/apps/server/src/persistence/Migrations/025_CanonicalizeModelSelections.ts index 57fdd8807..ef86ff101 100644 --- a/apps/server/src/persistence/Migrations/025_CanonicalizeModelSelections.ts +++ b/apps/server/src/persistence/Migrations/025_CanonicalizeModelSelections.ts @@ -7,12 +7,12 @@ export default Effect.gen(function* () { yield* sql` ALTER TABLE projection_projects ADD COLUMN default_model_selection TEXT - `.pipe(Effect.catch(() => Effect.void)); + `.pipe(Effect.catchCause(() => Effect.void)); yield* sql` ALTER TABLE projection_threads ADD COLUMN model_selection TEXT - `.pipe(Effect.catch(() => Effect.void)); + `.pipe(Effect.catchCause(() => Effect.void)); yield* sql` UPDATE projection_projects diff --git a/apps/server/src/persistence/Migrations/025_ProjectionProjectIconPath.ts b/apps/server/src/persistence/Migrations/025_ProjectionProjectIconPath.ts index 62d3a49d6..2297980c8 100644 --- a/apps/server/src/persistence/Migrations/025_ProjectionProjectIconPath.ts +++ b/apps/server/src/persistence/Migrations/025_ProjectionProjectIconPath.ts @@ -7,5 +7,5 @@ export default Effect.gen(function* () { yield* sql` ALTER TABLE projection_projects ADD COLUMN icon_path TEXT - `.pipe(Effect.catch(() => Effect.void)); + `.pipe(Effect.catchCause(() => Effect.void)); }); diff --git a/apps/server/src/persistence/Migrations/027_CanonicalizeModelSelectionsBackfill.ts b/apps/server/src/persistence/Migrations/027_CanonicalizeModelSelectionsBackfill.ts index fb5913f7b..30afc39c1 100644 --- a/apps/server/src/persistence/Migrations/027_CanonicalizeModelSelectionsBackfill.ts +++ b/apps/server/src/persistence/Migrations/027_CanonicalizeModelSelectionsBackfill.ts @@ -81,12 +81,12 @@ export default Effect.gen(function* () { yield* sql` ALTER TABLE projection_projects ADD COLUMN default_model_selection TEXT - `.pipe(Effect.catch(() => Effect.void)); + `.pipe(Effect.catchCause(() => Effect.void)); yield* sql` ALTER TABLE projection_threads ADD COLUMN model_selection TEXT - `.pipe(Effect.catch(() => Effect.void)); + `.pipe(Effect.catchCause(() => Effect.void)); const projectRows = yield* sql` SELECT