fix: pre-0.11 upgrade path — schema index order + v0.13.0 bun/TS detection#260
fix: pre-0.11 upgrade path — schema index order + v0.13.0 bun/TS detection#260Tacavar00 wants to merge 1 commit into
Conversation
…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.
|
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
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, +1 from a large-brain pre-0.11 upgrader. Thanks for this. |
|
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. |
Summary
Two chicken-and-egg bugs that block
bun install -g github:garrytan/gbrainupgrades 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_sourcetries to index a column that doesn't exist yetCREATE TABLE IF NOT EXISTS linksis a no-op on any pre-v0.11linkstable (pre-v0.11 had nolink_source/origin_page_id/origin_fieldcolumns). The very next line —CREATE INDEX IF NOT EXISTS idx_links_source ON links(link_source)— then errors out withcolumn "link_source" does not exist.src/core/migrate.tsv11 would add those columns viaALTER TABLE links ADD COLUMN IF NOT EXISTS link_source …, but the v0.11.0 migration orchestrator runsgbrain init --migrate-only(which runsschema.sql) as Phase A — before v11 gets a chance. So on any sufficiently old brain, Phase A fails with:Fix: add idempotent
ALTER TABLE … ADD COLUMN IF NOT EXISTSinline inschema.sql, between thefrom/toindex creates and thesource/originindex creates. No-op on fresh brains (theCREATE TABLEabove already has the columns). Self-heals old brains so theCREATE INDEXlines below succeed.Bug 2 —
const GBRAIN = process.execPathresolves tobun, not to gbrainFor
bun install -g github:…installs,~/.bun/bin/gbrainis a symlink tosrc/cli.tsandbunis the running process. Soprocess.execPathis/root/.bun/bin/bun. The v0.13.0 Phase B backfill then runs:…which bun interprets as "run script
extractfrom package.json" and fails witherror: Script not found "extract". Migration reports PARTIAL,gbrain doctorflipsminions_migration: fail, andgbrain apply-migrations --yesloops 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). Inbun build --compilemode the check is false andGBRAINstaysprocess.execPathas 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
gbrain init→gbrain apply-migrations --yes— no regression (defensive ALTERs are no-ops on a freshlinkstable).link_source/origin_page_id/origin_field):gbrain apply-migrations --yes— Phase A now passes, v0.13.0 Phase B now passes, migration completes.bun build --compile … && ./bin/gbrain apply-migrations --yes—GBRAINresolves 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:
plus
sed -i 's/const GBRAIN = process.execPath;/const GBRAIN = "gbrain";/' src/commands/migrations/v0_13_0.tsin the installed copy (which a reinstall re-breaks).🤖 Generated with Claude Code