{"record":{"id":"efc354f04caba025","repo":"gastownhall/beads","slug":"building-hook-migration-plan-w","errorCode":null,"errorMessage":"building hook migration plan: %w","messagePattern":"building hook migration plan: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/doctor_fix.go","lineNumber":448,"sourceCode":"\t// Summary\n\tfmt.Printf(\"\\nFix summary: %d fixed, %d errors\\n\", fixedCount, errorCount)\n\tif errorCount > 0 {\n\t\tfmt.Println(\"\\nSome fixes failed. Please review the errors above and apply manual fixes as needed.\")\n\t}\n}\n\nfunc fixPendingMigrations(path string) error {\n\tpending := doctor.DetectPendingMigrations(path)\n\tif len(pending) == 0 {\n\t\treturn nil\n\t}\n\n\tfor _, migration := range pending {\n\t\tswitch migration.Name {\n\t\tcase \"hooks\":\n\t\t\tplan, err := doctor.PlanHookMigration(path)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"building hook migration plan: %w\", err)\n\t\t\t}\n\n\t\t\texecPlan := buildHookMigrationExecutionPlan(plan)\n\t\t\tif len(execPlan.BlockingErrors) > 0 {\n\t\t\t\treturn fmt.Errorf(\"hook migration is blocked:\\n- %s\", strings.Join(execPlan.BlockingErrors, \"\\n- \"))\n\t\t\t}\n\n\t\t\tsummary, err := applyHookMigrationExecution(execPlan)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"applying hook migration: %w\", err)\n\t\t\t}\n\n\t\t\tfmt.Printf(\n\t\t\t\t\"  Hook migration applied: %d hook(s) written, %d artifact(s) retired, %d artifact(s) skipped\\n\",\n\t\t\t\tsummary.WrittenHookCount,\n\t\t\t\tsummary.RetiredCount,\n\t\t\t\tsummary.SkippedCount,\n\t\t\t)","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/doctor_fix.go#L430-L466","documentation":"fixPendingMigrations wraps failures from doctor.PlanHookMigration when building the plan to migrate git hooks. The %w-wrapped inner error explains why planning failed (e.g. unreadable hook directory or a malformed hook marker). It surfaces during `bd doctor fix` runs.","triggerScenarios":"Running `bd fix` / `bd doctor --fix` while a 'hooks' migration is pending and PlanHookMigration(path) returns an error — typically unreadable .git/hooks, a corrupt or half-written hook marker file, or permission errors on the hook files.","commonSituations":"A previous interrupted migration left a broken marker; .git/hooks owned by another user; running bd inside a worktree or bare repo where hooks paths differ.","solutions":["Read the wrapped cause (%w) printed below this message and address it directly","Inspect .git/hooks for corrupt or partially written hook files and remove/repair them","Re-run `bd doctor` to confirm the migration is still detected, then retry `bd fix`","If the marker is broken, let the repair path run: re-run `bd fix` (TestFixPendingMigrations_BrokenMarkerIsRepaired covers this)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if fi, err := os.Stat(filepath.Join(gitDir, \"hooks\")); err != nil || !fi.IsDir() {\n  return fmt.Errorf(\"hooks dir unreadable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := fixPendingMigrations(pending, path); err != nil {\n  if strings.Contains(err.Error(), \"building hook migration plan\") {\n    // inspect the wrapped cause with errors.Unwrap / %v for the real problem\n  }\n  return err\n}","preventionTips":["Keep .git/hooks writable and owned by the user running bd","Don't interrupt bd fix mid-migration; re-run doctor after any interrupt","Inspect hook marker files before hand-editing them","Run `bd doctor` before `bd fix` to preview what will change"],"tags":["migration","hooks","doctor","filesystem"],"backgroundTag":"hook-migration-plan-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}