{"record":{"id":"04766707c149089c","repo":"gastownhall/beads","slug":"counting-unbackfilled-dependencies-id-rows-for-mig","errorCode":null,"errorMessage":"counting unbackfilled dependencies.id rows for migration 0053: %w","messagePattern":"counting unbackfilled dependencies\\.id rows for migration 0053: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/migration_repairs.go","lineNumber":516,"sourceCode":"\t\t`, id, e.issueID, e.dependsOnIssueID, e.dependsOnWispID, e.dependsOnExternal); err != nil {\n\t\t\treturn fmt.Errorf(\"backfilling dependencies.id for migration 0053: %w\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// ensureDependenciesIDPrimaryKey finishes restoring dependencies.id to 0043's\n// canonical shape: NOT NULL and the table's PRIMARY KEY. It re-verifies both\n// independently of whether this pass just backfilled anything, so a re-entry\n// after a crash between the backfill and the key (or between MODIFY NOT NULL\n// and ADD PRIMARY KEY) finishes the remaining step(s) instead of re-running\n// ones already done -- MODIFY COLUMN restating an identical definition and\n// re-adding an already-present PRIMARY KEY are otherwise either redundant or\n// outright rejected as a duplicate key.\nfunc ensureDependenciesIDPrimaryKey(ctx context.Context, db DBConn) error {\n\tvar remainingNull int\n\tif err := db.QueryRowContext(ctx, \"SELECT COUNT(*) FROM dependencies WHERE id IS NULL\").Scan(&remainingNull); err != nil {\n\t\treturn fmt.Errorf(\"counting unbackfilled dependencies.id rows for migration 0053: %w\", err)\n\t}\n\tif remainingNull > 0 {\n\t\t// Fail with an actionable count now rather than let a subsequent\n\t\t// MODIFY COLUMN ... NOT NULL below abort with a generic \"column\n\t\t// cannot be null\" error, or silently key the table while leaving\n\t\t// NULL-id rows behind it.\n\t\treturn fmt.Errorf(\"migration 0053: %d dependencies row(s) have no depends_on_issue_id/depends_on_wisp_id/depends_on_external target and cannot be assigned an id (ck_dep_one_target should prevent this); repair manually before retrying\", remainingNull)\n\t}\n\n\tidIsPrimaryKey, err := schemaColumnInPrimaryKey(ctx, db, \"dependencies\", \"id\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"checking dependencies.id primary key: %w\", err)\n\t}\n\tif idIsPrimaryKey {\n\t\treturn nil\n\t}\n\n\tif _, err := db.ExecContext(ctx, \"ALTER TABLE dependencies MODIFY COLUMN id CHAR(36) NOT NULL\"); err != nil {","sourceCodeStart":498,"sourceCodeEnd":534,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/migration_repairs.go#L498-L534","documentation":"The migration 0053 repair counts rows in `dependencies` whose `id` is still NULL before making the column NOT NULL and keying it. This error wraps a failure of that `SELECT COUNT(*) FROM dependencies WHERE id IS NULL` probe itself — the count query failed, so the repair cannot safely proceed.","triggerScenarios":"ensureDependenciesIDPrimaryKey runs during startup schema repair and `db.QueryRowContext(...).Scan(&remainingNull)` errors: table missing/corrupt, connection lost, permissions revoked on dependencies, or Dolt server crashed mid-migration after the column was added but before the primary key was restored.","commonSituations":"Interrupted first upgrade to 0053 leaving the schema half-migrated; database file corruption or failed Dolt merge; running bd with a database user lacking SELECT on dependencies.","solutions":["Rerun `bd` so the repair retries; the probe is idempotent","Inspect the wrapped %w error for the real cause (no such table, permission denied, connection refused) and address it","Verify the table exists: query information_schema or run `bd dolt sql -q 'SHOW TABLES'`","If the schema is badly half-migrated, restore the database from backup and run migrations once, uninterrupted"],"exampleFix":"// before: half-migrated db crashes on every bd invocation\n// after: restore snapshot, rerun once\ncp -rf backup/beads-db .beads/beads-db ; bd ready","handlingStrategy":"retry","validationCode":"bd dolt sql -q 'SHOW TABLES LIKE \"dependencies\"' || echo 'missing/corrupt table'","typeGuard":null,"tryCatchPattern":"if err := ensureSchema(ctx, db); err != nil {\n    if strings.Contains(err.Error(), \"counting unbackfilled dependencies.id\") && transient(err) {\n        return retryWithBackoff(ensureSchema)\n    }\n    return fmt.Errorf(\"schema repair failed: %w\", err)\n}","preventionTips":["Do not interrupt bd mid-migration (avoid supervisor kill loops)","Use a DB account with SELECT on all beads tables","Monitor Dolt server logs during upgrades","Back up the database before upgrading"],"tags":["database","migration","sql","schema"],"backgroundTag":"migration-backfill-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}