fix(migrate): 0002 ALTER ADD COLUMN REFERENCES + DEFAULT — P0 deploy outage#87
Merged
viktor-shcherb merged 1 commit intomainfrom May 7, 2026
Merged
Conversation
…LL DEFAULT The post-merge deploy of M1 (#86) failed at migration 0002 with `Cannot add a REFERENCES column with non-NULL default value` and the container went into a crash loop, taking https://murmur.colophon-group.org down (502). Root cause: SQLite forbids `ALTER TABLE ADD COLUMN ... NOT NULL DEFAULT '<value>' REFERENCES ...` when foreign_keys=ON AND the table has existing rows. The local test suite hit it against a fresh `:memory:` DB (no rows), so the ALTER passed and the gate stayed green; the production `pipelines` table held the demo's existing row, so the ALTER tripped the rule. Fix: split the ALTER into two statements: ALTER TABLE pipelines ADD COLUMN publisher_id TEXT REFERENCES publishers(id); UPDATE pipelines SET publisher_id = 'pub_demo_seed' WHERE publisher_id IS NULL; The schema-level NOT NULL guarantee is traded for an application-level invariant — `mountPipelineRoutes` always supplies `publisher_id` from `c.var.publisher_id`. Test fixtures that INSERT directly into `pipelines` now include `publisher_id = 'pub_demo_seed'` explicitly (the previous DEFAULT was supplying it). A future migration can rebuild the table to recover schema-level NOT NULL once the migration runner supports a `PRAGMA foreign_keys=OFF` toggle (the toggle can't go inside a single BEGIN IMMEDIATE / COMMIT). Smoke-tested locally: identical `ALTER ... REFERENCES ... ; UPDATE` sequence applied successfully against a SQLite DB with an existing `pipelines` row (mirroring the failing prod state). All M1 tests + the grandfather-token + subcommand_bearer seed paths still pass (391 tests green). Closes the M1 deploy outage; the migration runner's BEGIN IMMEDIATE / COMMIT wrapping rolls the failed migration back atomically, so the production DB schema is unchanged and this fix can re-apply cleanly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
P0 hotfix: the post-merge deploy of M1 (#86) failed at migration 0002
and Murmur is currently down (502 on https://murmur.colophon-group.org;
container in a crash loop). This PR restores it.
Root cause. SQLite forbids
ALTER TABLE ADD COLUMN ... NOT NULL DEFAULT '<value>' REFERENCES ...whenforeign_keys=ONAND thetarget table already has rows. Locally the test suite ran against a
fresh
:memory:pipelines(no rows), so the ALTER succeeded. Inproduction the demo publisher's existing pipeline row triggered
Cannot add a REFERENCES column with non-NULL default value. Themigration runner's
BEGIN IMMEDIATE/COMMITwrapper rolled thefailed migration back atomically, so the prod DB is unchanged and this
fix can re-apply cleanly.
Fix. Split the ALTER into two statements:
The schema-level
NOT NULLis traded for an application-levelinvariant —
mountPipelineRoutesalways suppliespublisher_idfromc.var.publisher_id. Test fixtures that INSERT directly intopipelinesnow includepublisher_id = 'pub_demo_seed'explicitly(the previous DEFAULT was supplying it for the few tests that
bypassed the API).
Documented in
docs/auth.md/src/db/schema.md. A future migrationcan rebuild the table to recover schema-level
NOT NULLonce themigration runner supports
PRAGMA foreign_keys=OFF(the toggle can'tgo inside a single transaction).
Test plan
existing
pipelinesrow (mirrors prod state) — fix applies cleanly.pnpm test:unit— 391 tests pass (test fixtures updated for theexplicit
publisher_idvalue).pnpm lint,pnpm typecheck,pnpm grep:all— green./health=200,ssh murmur 'docker logs --tail 30 murmur'showsbootstrap.demo_publisher_seeded.start-run.tsflow still authenticates.🤖 Generated with Claude Code