gastownhall/beads · info

%s does not require migration

Error message

%s does not require migration

What it means

The sibling of the unsupported-state error: when the hook's State falls into the default case AND NeedsMigration is false, the hook is already migrated (or was never managed), so applying a migration is a no-op request. bd refuses with this explicit message instead of overwriting a hook that doesn't need changes.

Source

Thrown at cmd/bd/migrate_hooks_apply.go:225

	}
	return fmt.Sprintf("%s (%s): %s", hook.Name, hook.State, suggestion)
}

func chooseHookMigrationWriteSource(hook doctor.HookMigrationHookPlan) (hookMigrationWriteSource, string, error) {
	switch hook.State {
	case "legacy_only":
		return hookMigrationWriteFromTemplate, "", nil
	case "legacy_with_old_sidecar", "legacy_with_both_sidecars", "missing_with_old_sidecar", "missing_with_both_sidecars":
		return hookMigrationWriteFromOld, hook.HookPath + ".old", nil
	case "legacy_with_backup_sidecar", "missing_with_backup_sidecar":
		return hookMigrationWriteFromBackup, hook.HookPath + ".backup", nil
	case "custom_with_sidecars":
		return hookMigrationWriteFromHookFile, hook.HookPath, nil
	default:
		if hook.NeedsMigration {
			return "", "", fmt.Errorf("%s has unsupported migration state %q", hook.Name, hook.State)
		}
		return "", "", fmt.Errorf("%s does not require migration", hook.Name)
	}
}

type preparedHookWrite struct {
	HookName string
	Path     string
	Content  []byte
}

func applyHookMigrationExecution(execPlan hookMigrationExecutionPlan) (hookMigrationApplySummary, error) {
	if len(execPlan.BlockingErrors) > 0 {
		return hookMigrationApplySummary{}, fmt.Errorf(
			"hook migration blocked by %d issue(s): %s",
			len(execPlan.BlockingErrors),
			strings.Join(execPlan.BlockingErrors, "; "),
		)
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Nothing to fix — the hook is already migrated; skip it
  2. Use the plan/dry-run output to filter which hooks actually need migration before applying
  3. Check the hook's detected state (`bd migrate hooks` list) before forcing apply
  4. If the hook should be managed by bd, re-install it from template rather than applying migration
Defensive patterns

Strategy: validation

Validate before calling

// filter to hooks that actually need migration
const pending = hooks.filter(h => h.NeedsMigration);
applyMigration(pending);

Type guard

function needsMigration(h) { return h.NeedsMigration === true }

Try / catch

if err := apply(h); err != nil && strings.Contains(err.Error(), "does not require migration") {
    // treat as success / skip
    continue
}

Prevention

When it happens

Trigger: Running `bd migrate hooks apply` (or fixPendingMigrations) for a hook whose detected state is not one of the pending-migration states and whose NeedsMigration flag is false — e.g. already migrated, custom hook without sidecars, or user-managed hook.

Common situations: Re-running apply after a successful migration; applying migration to a repo whose hooks were installed by another tool; scripting apply across many repos where some are already done.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/8982e95d26fbad3b. Report an issue: GitHub.