Hi Garry — running into a chicken-and-egg in initSchema when upgrading an existing PGLite brain from v0.12.3 (schema version 10) to master (v0.14.2).
Reproducer
Starting from a brain at schema version 10 (the v0.12.3 baseline — drop_timeline_search_trigger):
cd ~/gbrain-tmp
git fetch origin && git reset --hard origin/master # lands on v0.14.2
bun install && bun link
gbrain apply-migrations --yes
Output:
=== Applying migration v0.12.2: JSONB double-encode repair ===
column "link_source" does not exist
Migration v0.12.2 reported status=failed.
Same error from gbrain init --migrate-only directly.
Root cause
src/core/pglite-schema.ts:82-83 has:
CREATE INDEX IF NOT EXISTS idx_links_source ON links(link_source);
CREATE INDEX IF NOT EXISTS idx_links_origin ON links(origin_page_id);
These reference columns that are added by migration v11 (links_provenance_columns) in src/core/migrate.ts:288. But PGLiteEngine.initSchema() runs PGLITE_SCHEMA_SQL before it calls runMigrations:
// src/core/pglite-engine.ts:63-70
async initSchema(): Promise<void> {
await this.db.exec(PGLITE_SCHEMA_SQL); // <-- fails here on existing v10 brain
const { applied } = await runMigrations(this);
...
}
CREATE INDEX IF NOT EXISTS guards by index name, not column existence — so for a brain already carrying idx_links_from / idx_links_to / etc. from its v10 state, the new idx_links_source doesn't exist yet and must be created, but the column it references also doesn't exist yet. SQL fails, runMigrations never runs, v11 never applies, user is stuck.
A fresh brain (gbrain init --pglite) isn't affected — the CREATE TABLE defines link_source in the initial schema, then the indexes create cleanly. Only users who went through the v0.11/v0.12 wave hit this.
What I tried
gbrain apply-migrations --yes — fails at Phase A
gbrain apply-migrations --force-retry 0.12.2 → re-run — same failure
gbrain init --migrate-only directly — same failure
- I considered a direct invocation of
runMigrations(engine) to apply v11 first and then retry initSchema, but that bypasses the sanctioned CLI path and felt wrong to apply to a production brain.
Reverted cleanly to v0.12.3 and held.
Possible fixes
- Swap order in
initSchema: call runMigrations first, then exec PGLITE_SCHEMA_SQL. Upstream migrations add columns → subsequent CREATE INDEX succeeds. A fresh brain would first create the tables (no rows, nothing to migrate), then re-exec schema SQL as a no-op.
- Or guard the index creation: wrap the two problematic
CREATE INDEX statements with a conditional that checks information_schema.columns for the target column, similar to the PG15+ guard in migrate.ts v11.
- Or add
ALTER TABLE IF NOT EXISTS ADD COLUMN for the three new columns in the schema SQL itself, ahead of the indexes — makes the SQL safely reentrant across schema generations.
Environment
- gbrain source at
b5fa3d0 (v0.14.2)
- PGLite 0.4.4
- bun 1.3.12
- Linux ARM64 (NVIDIA DGX Spark)
- Brain: ~2,066 pages, schema version 10, PGLite (single-user)
Happy to test any fix branch. Thanks for shipping the v0.13 wave — the graph enrichment from frontmatter indexing is exciting, just need a clear path to get there from an existing brain.
Hi Garry — running into a chicken-and-egg in
initSchemawhen upgrading an existing PGLite brain from v0.12.3 (schema version 10) to master (v0.14.2).Reproducer
Starting from a brain at schema version 10 (the v0.12.3 baseline —
drop_timeline_search_trigger):Output:
Same error from
gbrain init --migrate-onlydirectly.Root cause
src/core/pglite-schema.ts:82-83has:These reference columns that are added by migration v11 (
links_provenance_columns) insrc/core/migrate.ts:288. ButPGLiteEngine.initSchema()runsPGLITE_SCHEMA_SQLbefore it callsrunMigrations:CREATE INDEX IF NOT EXISTSguards by index name, not column existence — so for a brain already carryingidx_links_from/idx_links_to/ etc. from its v10 state, the newidx_links_sourcedoesn't exist yet and must be created, but the column it references also doesn't exist yet. SQL fails,runMigrationsnever runs, v11 never applies, user is stuck.A fresh brain (
gbrain init --pglite) isn't affected — the CREATE TABLE defineslink_sourcein the initial schema, then the indexes create cleanly. Only users who went through the v0.11/v0.12 wave hit this.What I tried
gbrain apply-migrations --yes— fails at Phase Agbrain apply-migrations --force-retry 0.12.2→ re-run — same failuregbrain init --migrate-onlydirectly — same failurerunMigrations(engine)to apply v11 first and then retryinitSchema, but that bypasses the sanctioned CLI path and felt wrong to apply to a production brain.Reverted cleanly to v0.12.3 and held.
Possible fixes
initSchema: callrunMigrationsfirst, then execPGLITE_SCHEMA_SQL. Upstream migrations add columns → subsequentCREATE INDEXsucceeds. A fresh brain would first create the tables (no rows, nothing to migrate), then re-exec schema SQL as a no-op.CREATE INDEXstatements with a conditional that checksinformation_schema.columnsfor the target column, similar to the PG15+ guard inmigrate.tsv11.ALTER TABLE IF NOT EXISTS ADD COLUMNfor the three new columns in the schema SQL itself, ahead of the indexes — makes the SQL safely reentrant across schema generations.Environment
b5fa3d0(v0.14.2)Happy to test any fix branch. Thanks for shipping the v0.13 wave — the graph enrichment from frontmatter indexing is exciting, just need a clear path to get there from an existing brain.