What broke
Upgrading from a working v0.18.2 install (Supabase Postgres, schema_version=24, 0 pages) to v0.27.0:
$ git -C ~/gbrain checkout ee9ceb3 # v0.27 commit
$ bun install
$ gbrain apply-migrations --yes
...
NOTICE: relation "content_chunks" already exists, skipping
NOTICE: relation "idx_chunks_page_index" already exists, skipping
NOTICE: relation "idx_chunks_page" already exists, skipping
NOTICE: relation "idx_chunks_embedding" already exists, skipping
column "search_vector" does not exist
Phase A (schema) failed: Command failed: gbrain init --migrate-only. Aborting; re-run after fixing.
Migration v0.11.0 reported status=failed.
Root cause
src/schema.sql declares content_chunks.search_vector and indexes it in the same idempotent setup block:
- L131:
CREATE TABLE IF NOT EXISTS content_chunks ( ... search_vector TSVECTOR ... )
- L141:
CREATE INDEX IF NOT EXISTS idx_chunks_search_vector ON content_chunks USING GIN(search_vector);
- L150–164: trigger that maintains
search_vector on INSERT/UPDATE.
On a pre-v0.27 install, content_chunks already exists from old schema without search_vector. CREATE TABLE IF NOT EXISTS is a
no-op when the table exists, so the new column is never added. The next statement (CREATE INDEX ... USING GIN(search_vector))
fails because the column isn't there.
Migration v26 (content_chunks_code_metadata) is the path that's supposed to add search_vector to existing content_chunks, but it
runs after gbrain init --migrate-only (which executes schema.sql first). The schema-setup phase blows up before the migration
runner gets to v26.
The same pattern for pages.search_vector (L478–480) is fine because that one uses an explicit ALTER TABLE pages ADD COLUMN IF NOT EXISTS search_vector tsvector before the index. The fix is to apply the same ALTER TABLE ... IF NOT EXISTS pattern to
content_chunks.search_vector, OR to remove the column from schema.sql entirely and let migration v26 own it.
Repro
# Fresh v0.18.2 install
git clone https://github.com/garrytan/gbrain ~/gbrain-repro && cd ~/gbrain-repro
git checkout 08b3698 # v0.18.2
bun install && bun link
gbrain init --supabase --non-interactive --json # against an empty Supabase project
# Upgrade
git checkout ee9ceb3 # v0.27.0 commit
bun install
gbrain apply-migrations --yes
# fails as shown above
Workaround used
Drop public-schema tables, run gbrain init --supabase --non-interactive --json clean. Brain had 0 pages so this was free; data-bearing
brains can't take this path.
Suggested fix
In src/schema.sql, replace the inline search_vector TSVECTOR column in the content_chunks CREATE TABLE with an explicit additive
step right after the table create:
CREATE TABLE IF NOT EXISTS content_chunks (
-- ... existing columns ...
-- (drop search_vector from the inline column list)
);
ALTER TABLE content_chunks ADD COLUMN IF NOT EXISTS search_vector TSVECTOR;
CREATE INDEX IF NOT EXISTS idx_chunks_search_vector ON content_chunks USING GIN(search_vector);
This matches what pages.search_vector already does at L478–480 and makes the schema setup idempotent on existing installs.
Environment
- gbrain commits involved:
08b3698 (v0.18.2 baseline) → ee9ceb3 (v0.27.0)
- engine: postgres (Supabase pooler)
- macOS 25.4.0 / Bun 1.3.13
- 0 pages at upgrade time (data-bearing brains likely hit this harder)
Side notes (not blockers — file separately if useful)
gbrain init --help doesn't print help; it falls through and runs init on PGLite. Works for most subcommands but not init.
gbrain init (no args) silently overwrites a Supabase config with a fresh PGLite one. Consider a confirm prompt or a guard when
~/.gbrain/config.json already declares engine: postgres.
gbrain upgrade calls bun update gbrain. For bun link installs (the path the README recommends) this is a no-op or wrong; git pull && bun install is the real upgrade. Worth a heads-up in runUpgrade() when detectInstallMethod() sees a linked clone.
What broke
Upgrading from a working v0.18.2 install (Supabase Postgres, schema_version=24, 0 pages) to v0.27.0:
Root cause
src/schema.sqldeclarescontent_chunks.search_vectorand indexes it in the same idempotent setup block:CREATE TABLE IF NOT EXISTS content_chunks ( ... search_vector TSVECTOR ... )CREATE INDEX IF NOT EXISTS idx_chunks_search_vector ON content_chunks USING GIN(search_vector);search_vectoron INSERT/UPDATE.On a pre-v0.27 install,
content_chunksalready exists from old schema withoutsearch_vector.CREATE TABLE IF NOT EXISTSis ano-op when the table exists, so the new column is never added. The next statement (
CREATE INDEX ... USING GIN(search_vector))fails because the column isn't there.
Migration v26 (
content_chunks_code_metadata) is the path that's supposed to addsearch_vectorto existingcontent_chunks, but itruns after
gbrain init --migrate-only(which executesschema.sqlfirst). The schema-setup phase blows up before the migrationrunner gets to v26.
The same pattern for
pages.search_vector(L478–480) is fine because that one uses an explicitALTER TABLE pages ADD COLUMN IF NOT EXISTS search_vector tsvectorbefore the index. The fix is to apply the sameALTER TABLE ... IF NOT EXISTSpattern tocontent_chunks.search_vector, OR to remove the column fromschema.sqlentirely and let migration v26 own it.Repro
Workaround used
Drop public-schema tables, run
gbrain init --supabase --non-interactive --jsonclean. Brain had 0 pages so this was free; data-bearingbrains can't take this path.
Suggested fix
In
src/schema.sql, replace the inlinesearch_vector TSVECTORcolumn in thecontent_chunksCREATE TABLEwith an explicit additivestep right after the table create:
This matches what
pages.search_vectoralready does at L478–480 and makes the schema setup idempotent on existing installs.Environment
08b3698(v0.18.2 baseline) →ee9ceb3(v0.27.0)Side notes (not blockers — file separately if useful)
gbrain init --helpdoesn't print help; it falls through and runs init on PGLite. Works for most subcommands but notinit.gbrain init(no args) silently overwrites a Supabase config with a fresh PGLite one. Consider a confirm prompt or a guard when~/.gbrain/config.jsonalready declaresengine: postgres.gbrain upgradecallsbun update gbrain. Forbun linkinstalls (the path the README recommends) this is a no-op or wrong;git pull && bun installis the real upgrade. Worth a heads-up inrunUpgrade()whendetectInstallMethod()sees a linked clone.