Skip to content

fix: pre-0.11 upgrade path — schema index order + v0.13.0 bun/TS detection#260

Closed
Tacavar00 wants to merge 1 commit into
garrytan:masterfrom
Tacavar00:fix/pre-0.11-migration-path
Closed

fix: pre-0.11 upgrade path — schema index order + v0.13.0 bun/TS detection#260
Tacavar00 wants to merge 1 commit into
garrytan:masterfrom
Tacavar00:fix/pre-0.11-migration-path

Conversation

@Tacavar00

Copy link
Copy Markdown

Summary

Two chicken-and-egg bugs that block bun install -g github:garrytan/gbrain upgrades from ancient versions. Both observed migrating a real 0.5.0 brain (2,748 pages, production) to 0.14.1 on 2026-04-20.

Bug 1 — idx_links_source tries to index a column that doesn't exist yet

CREATE TABLE IF NOT EXISTS links is a no-op on any pre-v0.11 links table (pre-v0.11 had no link_source / origin_page_id / origin_field columns). The very next line — CREATE INDEX IF NOT EXISTS idx_links_source ON links(link_source) — then errors out with column "link_source" does not exist.

src/core/migrate.ts v11 would add those columns via ALTER TABLE links ADD COLUMN IF NOT EXISTS link_source …, but the v0.11.0 migration orchestrator runs gbrain init --migrate-only (which runs schema.sql) as Phase A — before v11 gets a chance. So on any sufficiently old brain, Phase A fails with:

column "link_source" 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.

Fix: add idempotent ALTER TABLE … ADD COLUMN IF NOT EXISTS inline in schema.sql, between the from/to index creates and the source/origin index creates. No-op on fresh brains (the CREATE TABLE above already has the columns). Self-heals old brains so the CREATE INDEX lines below succeed.

Bug 2 — const GBRAIN = process.execPath resolves to bun, not to gbrain

For bun install -g github:… installs, ~/.bun/bin/gbrain is a symlink to src/cli.ts and bun is the running process. So process.execPath is /root/.bun/bin/bun. The v0.13.0 Phase B backfill then runs:

execSync(`${GBRAIN} extract links --source db --include-frontmatter`)
# → bun extract links --source db --include-frontmatter

…which bun interprets as "run script extract from package.json" and fails with error: Script not found "extract". Migration reports PARTIAL, gbrain doctor flips minions_migration: fail, and gbrain apply-migrations --yes loops forever because every re-run hits the same wall.

Fix: detect bun-TS mode via process.argv[1].endsWith('.ts') and build the command as ${execPath} ${scriptPath} in that case (→ bun /path/to/cli.ts extract links …, which bun executes correctly). In bun build --compile mode the check is false and GBRAIN stays process.execPath as originally intended. Original concern about PATH shadowing is preserved in the comment — this just adds a branch for the bun-TS install path.

Test plan

  • Fresh Postgres install: gbrain initgbrain apply-migrations --yes — no regression (defensive ALTERs are no-ops on a fresh links table).
  • Pre-v0.11 Postgres brain (simulate by dropping link_source / origin_page_id / origin_field): gbrain apply-migrations --yes — Phase A now passes, v0.13.0 Phase B now passes, migration completes.
  • Compiled binary mode: bun build --compile … && ./bin/gbrain apply-migrations --yesGBRAIN resolves to the compiled binary (argv[1] is not .ts), no regression in compiled path.

Workaround the downstream user applied

Until this merges, the manual patch is:

ALTER TABLE links ADD COLUMN IF NOT EXISTS link_source TEXT;
ALTER TABLE links ADD CONSTRAINT links_link_source_check CHECK (link_source IS NULL OR link_source IN ('markdown','frontmatter','manual'));
ALTER TABLE links ADD COLUMN IF NOT EXISTS origin_page_id INTEGER REFERENCES pages(id) ON DELETE SET NULL;
ALTER TABLE links ADD COLUMN IF NOT EXISTS origin_field TEXT;

plus sed -i 's/const GBRAIN = process.execPath;/const GBRAIN = "gbrain";/' src/commands/migrations/v0_13_0.ts in the installed copy (which a reinstall re-breaks).

🤖 Generated with Claude Code

…ction

Two chicken-and-egg bugs that block `bun install -g github:garrytan/gbrain`
upgrades from ancient versions (observed migrating a 0.5.0 brain to 0.14.1):

1. **`CREATE INDEX idx_links_source` fires before `link_source` exists
   on pre-v0.11 `links` tables.** `CREATE TABLE IF NOT EXISTS links` is
   a no-op on an existing pre-v0.11 table (which has no `link_source` /
   `origin_page_id` / `origin_field` columns), so the subsequent
   `CREATE INDEX IF NOT EXISTS idx_links_source ON links(link_source)`
   errors out with `column "link_source" does not exist`. migrate.ts v11
   would add those columns, but Phase A of the v0.11.0 migration runs
   `gbrain init --migrate-only` (which runs schema.sql) FIRST, so v11
   never gets a chance. Fix: add idempotent `ALTER TABLE … ADD COLUMN
   IF NOT EXISTS` statements inline in schema.sql, between the existing
   `from`/`to` index creates and the `source`/`origin` index creates.
   No-op on fresh brains (the CREATE TABLE already has the columns);
   self-heals old brains. Check-constraint is added via `DO $$ … $$`
   so it's idempotent too.

2. **`const GBRAIN = process.execPath` in v0.13.0 Phase B resolves to
   the bun binary, not the gbrain CLI.** For `bun install -g
   github:garrytan/gbrain` installs, `~/.bun/bin/gbrain` is a symlink
   to `src/cli.ts` and `bun` is the running process — so `execPath`
   is `/path/to/bun`. `execSync(\`${GBRAIN} extract links …\`)` then
   becomes `bun extract links …`, which bun interprets as "run script
   `extract` from package.json" and fails with `Script not found
   "extract"`. Migration reports PARTIAL, doctor flips
   `minions_migration: fail`, user has to know the workaround.
   Fix: detect bun-TS mode via `process.argv[1].endsWith('.ts')`
   and build the command as `${execPath} ${scriptPath}` in that case
   (so it becomes `bun /path/to/cli.ts extract links …` — which bun
   executes correctly). In compiled (`bun build --compile`) mode the
   check is false and `GBRAIN` stays `execPath` as originally intended.
   Keep the rest of the comment — the author's original concern about
   PATH shadowing is still valid.

Both observed during a 0.5.0 → 0.14.1 production upgrade on 2026-04-20.
Manual workaround notes in the downstream user's memory; this PR is the
upstream fix so the workarounds aren't needed.
@notjbg

notjbg commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Hit both of these failure modes today upgrading a 31k-page brain from 0.12.0 → 0.14.2:

Schema index order bug — On initial gbrain init --migrate-only during v0.11.0 Phase A, SCHEMA_SQL hit column "link_source" does not exist because the CREATE INDEX idx_links_source ON links(link_source) in src/schema.sql fires before migrate.ts v11 adds the column. Had to manually ALTER TABLE links ADD COLUMN link_source ... via the Supabase MCP before apply-migrations could proceed. This PR's defensive ALTERs in schema.sql would have prevented the manual intervention.

process.execPath bug — v0.13.0 Phase B ran bun extract links --source db --include-frontmatter instead of gbrain extract .... Because process.execPath in a bun install -g install resolves to the bun interpreter (not the gbrain CLI), bun interpreted extract as a script name, triggered its init flow, scaffolded .cursor/, .gitignore, and appended "private": true + peerDependencies into the gbrain module's own package.json. Failed with error: Script not found "extract". This PR's TS-mode detection (isBunRunningTS ? \${execPath} ${scriptPath}` : execPath`) fixes it cleanly.

Both fixes are correct and worth landing. The schema.sql defensive block is especially important because it closes the bootstrap hole that blocks every subsequent migration — without it, gbrain apply-migrations can't even start on an old-schema brain.

+1 from a large-brain pre-0.11 upgrader. Thanks for this.

@garrytan

Copy link
Copy Markdown
Owner

Closing — Pre-v0.11 upgrade path covered by applyForwardReferenceBootstrap (v0.22.6.1).

Thanks for the report. If anything still reproduces on the latest release, please reopen with the version + repro.

@garrytan garrytan closed this May 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants