{"record":{"id":"d6b091e349a493ea","repo":"gastownhall/beads","slug":"checking-s-id-for-the-pre-0058-repair-w","errorCode":null,"errorMessage":"checking %s.id for the pre-0058 repair: %w","messagePattern":"checking (.+?)\\.id for the pre-0058 repair: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/wisp_dep_forward_repair.go","lineNumber":189,"sourceCode":"// depends_on_id nor id, which no lineage produces on purpose and which only a\n// process killed between this repair's DROP COLUMN and its ADD COLUMN can\n// reach. Detecting the second is what makes the repair resumable rather than\n// leaving a keyless table behind for 0058 to complete over.\n//\n// A fresh store has id and no generated column and is not repaired: 0058\n// applies to it cleanly, and the constraints are already there from creation.\nfunc wispDepNeedsForwardRepair(ctx context.Context, db DBConn) (bool, error) {\n\tgenerated, err := wispDepHasStoredGeneratedDependsOnID(ctx, db)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tif generated {\n\t\treturn true, nil\n\t}\n\n\thasID, err := schemaColumnExists(ctx, db, wispDepTable, \"id\")\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"checking %s.id for the pre-0058 repair: %w\", wispDepTable, err)\n\t}\n\tif hasID {\n\t\t// Final lineage. Still finish the job if a prior pass was killed\n\t\t// between adding the surrogate key and adding every constraint: the\n\t\t// steps below are individually guarded, so this is a no-op once the\n\t\t// shape is complete.\n\t\treturn wispDepMissingAnyFinalConstraint(ctx, db)\n\t}\n\n\t// Neither depends_on_id nor id: a mid-rebuild crash. Resume.\n\treturn true, nil\n}\n\nfunc wispDepMissingAnyFinalConstraint(ctx context.Context, db DBConn) (bool, error) {\n\tfor _, c := range wispDepFinalConstraints {\n\t\tpresent, err := schemaConstraintExists(ctx, db, wispDepTable, c.name)\n\t\tif err != nil {\n\t\t\treturn false, err","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/wisp_dep_forward_repair.go#L171-L207","documentation":"Wraps a failure from schemaColumnExists when checking whether wisp_dependencies already has an `id` column, which decides whether the pre-0058 repair must add the surrogate key. The column-existence metadata query failed; the repair aborts rather than guessing the table's shape. Called from repairWispDependenciesForwardShape via wispDepNeedsForwardRepair.","triggerScenarios":"wispDepNeedsForwardRepair calls schemaColumnExists(ctx, db, \"wisp_dependencies\", \"id\") and the information_schema column lookup errors (connection failure, permission denial, table metadata unreadable).","commonSituations":"Dropped connection mid-upgrade; restricted DB user cannot read COLUMNS metadata; Dolt server under load timing out on metadata queries during startup migration.","solutions":["Inspect the wrapped cause (%w) — typically a connection or privilege error.","Reconnect and re-run; every repair step is individually guarded so the repair resumes safely.","Grant the DB user SELECT on information_schema.","If wisp_dependencies metadata is unreadable/corrupt, restore from backup or re-init from the .beads/issues.jsonl export."],"exampleFix":"// before\nhasID, err := schemaColumnExists(...) // checking wisp_dependencies.id ... driver: bad connection\n// after\nif err := db.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"db unreachable before repair: %w\", err)\n}\nif err := repairWispDependenciesForwardShape(ctx, db); err != nil {\n    return err\n}","handlingStrategy":"try-catch","validationCode":"var hasID bool\nrows, err := db.QueryContext(ctx, `SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_NAME = 'wisp_dependencies' AND COLUMN_NAME = 'id'`)\nif err == nil && rows.Next() {\n    _ = rows.Scan(&hasID)\n}\nrows.Close()\n_ = hasID // metadata readable; safe to proceed with repair","typeGuard":null,"tryCatchPattern":"err := repairWispDependenciesForwardShape(ctx, db)\nif err != nil && strings.Contains(err.Error(), \"checking wisp_dependencies.id\") {\n    // metadata probe failed: reconnect and retry once\n    if err := db.PingContext(ctx); err == nil {\n        err = repairWispDependenciesForwardShape(ctx, db)\n    }\n}\nreturn err","preventionTips":["Ping the DB before running schema repairs.","Ensure information_schema read privileges for the migration user.","Re-run the repair rather than hand-editing schema after a failure — steps are guarded.","Monitor DB load so metadata queries do not time out during startup migrations."],"tags":["database","schema-repair","migration","introspection"],"backgroundTag":"schema-introspection-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}