From bcdfb177e453a916f8428b0f36191da7cac7c33f Mon Sep 17 00:00:00 2001 From: jbarol Date: Wed, 10 Jun 2026 13:29:06 -0700 Subject: [PATCH] docs(migrations): NULL embeddings BEFORE the column-type alter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Postgres recipe ordered ALTER COLUMN TYPE vector(N) before the UPDATE that clears stale embeddings. pgvector refuses to cast existing vectors across dimensions ('expected 1024 dimensions, not 1536'), so the recipe as written aborts the transaction on any brain that has embeddings — which is every brain doing this migration. Swap the steps: NULLs cast fine. --- docs/embedding-migrations.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/embedding-migrations.md b/docs/embedding-migrations.md index e9c425128..9fdc40a8f 100644 --- a/docs/embedding-migrations.md +++ b/docs/embedding-migrations.md @@ -115,12 +115,17 @@ BEGIN; -- 1. Drop the HNSW index. It can't survive the column type change. DROP INDEX IF EXISTS idx_chunks_embedding; --- 2. Alter the column type. -ALTER TABLE content_chunks ALTER COLUMN embedding TYPE vector(); - --- 3. Clear stale embeddings so they don't survive into the new space. +-- 2. Clear stale embeddings FIRST. This must happen BEFORE the column +-- alter: pgvector refuses to cast existing vectors across dimensions +-- ("expected dimensions, not "), so altering a +-- column that still holds old-width vectors aborts the transaction. +-- NULLs cast fine. (The old vectors are unusable in the new space +-- anyway — wiping them is step 3 of the recipe's rationale.) UPDATE content_chunks SET embedding = NULL, embedded_at = NULL; +-- 3. Alter the column type (all rows are NULL now, so the cast succeeds). +ALTER TABLE content_chunks ALTER COLUMN embedding TYPE vector(); + -- 4. Recreate the HNSW index ONLY IF dims <= 2000. Above that, leave it -- indexless and rely on exact scans (gbrain searchVector handles this -- automatically — search just gets slower, not broken).