gastownhall/beads · error
hook migration is blocked: - %s
Error message
hook migration is blocked: - %s
What it means
During a pending 'hooks' migration, fixPendingMigrations builds an execution plan and checks execPlan.BlockingErrors. If any blocking errors exist, it refuses to proceed and returns this error listing them. This is a deliberate safety stop, not a crash: applying the migration would break or overwrite hooks.
Source
Thrown at cmd/bd/doctor_fix.go:453
}
func fixPendingMigrations(path string) error {
pending := doctor.DetectPendingMigrations(path)
if len(pending) == 0 {
return nil
}
for _, migration := range pending {
switch migration.Name {
case "hooks":
plan, err := doctor.PlanHookMigration(path)
if err != nil {
return fmt.Errorf("building hook migration plan: %w", err)
}
execPlan := buildHookMigrationExecutionPlan(plan)
if len(execPlan.BlockingErrors) > 0 {
return fmt.Errorf("hook migration is blocked:\n- %s", strings.Join(execPlan.BlockingErrors, "\n- "))
}
summary, err := applyHookMigrationExecution(execPlan)
if err != nil {
return fmt.Errorf("applying hook migration: %w", err)
}
fmt.Printf(
" Hook migration applied: %d hook(s) written, %d artifact(s) retired, %d artifact(s) skipped\n",
summary.WrittenHookCount,
summary.RetiredCount,
summary.SkippedCount,
)
default:
return fmt.Errorf("no automatic fix available for pending migration %q", migration.Name)
}
}
View on GitHub (pinned to 71377f2769)
Solutions
- Read the bullet list of blocking errors in the message and resolve each one (usually preserve or move your custom hooks)
- Back up conflicting hook files and re-run `bd fix`
- If another hook manager owns the hooks, configure that manager to invoke the beads hook instead of letting bd overwrite
- Re-run `bd doctor` after fixing to confirm the migration can proceed
Example fix
// before: custom hook clobbered by migration #!/bin/sh exec my-linter // after: chain the beads hook #!/bin/sh bd hook "$@" || exit 1 exec my-linter
Defensive patterns
Strategy: validation
Validate before calling
plan, err := doctor.PlanHookMigration(path)
if err == nil {
execPlan := buildHookMigrationExecutionPlan(plan)
for _, e := range execPlan.BlockingErrors { fmt.Println("blocking:", e) }
} Try / catch
if err := fixPendingMigrations(pending, path); err != nil {
if strings.HasPrefix(err.Error(), "hook migration is blocked") {
fmt.Fprintln(os.Stderr, "Resolve blocking errors manually, then re-run.")
return err // do not retry blindly
}
} Prevention
- Don't hand-edit beads-managed hook files; chain instead of replacing
- Coordinate with other hook managers (husky, pre-commit) to invoke bd hooks
- Run `bd doctor` to inspect planned hook changes before applying
- Keep custom hook logic in separate script files invoked from the managed hook
When it happens
Trigger: `bd fix` / `bd doctor --fix` with a pending hooks migration where buildHookMigrationExecutionPlan reports one or more BlockingErrors — e.g. a user-modified hook file that would be overwritten, unwritable hook path, or conflicting hook content.
Common situations: Developer customized pre-commit/post-commit hooks manually; hooks managed by another tool (husky, pre-commit framework) conflict with beads' hooks.
Related errors
- building hook migration plan: %w
- applying hook migration: %w
- not a git repository
- failed to install hooks: %w
- no automatic fix available for pending migration %q
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/e169cc890e56e2ce.
Report an issue: GitHub.