gastownhall/beads · error
artifact collision for %s: %s already exists with different
Error message
artifact collision for %s: %s already exists with different content
What it means
This is the pre-apply collision abort: the destination sidecar already exists AND its content differs from the source sidecar, so blindly retiring would overwrite user-modified content. validateRetireCollisionPolicy fails fast before any operation is applied, leaving the filesystem untouched.
Source
Thrown at cmd/bd/migrate_hooks_apply.go:371
}
if !sourceExists {
continue
}
destinationExists, err := pathExists(op.DestinationPath)
if err != nil {
return fmt.Errorf("checking destination sidecar %s: %w", op.DestinationPath, err)
}
if !destinationExists {
continue
}
equal, err := filesEqual(op.SourcePath, op.DestinationPath)
if err != nil {
return fmt.Errorf("comparing sidecars %s and %s: %w", op.SourcePath, op.DestinationPath, err)
}
if !equal {
return fmt.Errorf(
"artifact collision for %s: %s already exists with different content",
op.SourcePath,
op.DestinationPath,
)
}
}
return nil
}
func retireHookSidecar(op hookMigrationRetireOp) (string, error) {
sourceExists, err := pathExists(op.SourcePath)
if err != nil {
return "", fmt.Errorf("checking sidecar %s: %w", op.SourcePath, err)
}
if !sourceExists {
return "", nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Diff the two files to see what differs: diff <source> <destination>.
- If the destination content is obsolete, delete or rename it and re-run `bd migrate`.
- If the source content is what you want, back up the destination, remove it, and re-run (the source will be renamed over).
- Merge any intentional customizations into the new source sidecar before re-running.
Example fix
// before $ diff ~/.bd/hooks/old.sh ~/.bd/hooks/new.sh # differs // after $ mv ~/.bd/hooks/new.sh ~/.bd/hooks/new.sh.bak $ bd migrate # completes; source content wins
Defensive patterns
Strategy: validation
Validate before calling
if same, _ := filesEqual(src, dst); !same {
fmt.Printf("collision: %s differs from %s; back up or merge first\n", src, dst)
os.Exit(1)
} Try / catch
if err := validateRetireCollisionPolicy(ops); err != nil {
if strings.Contains(err.Error(), "artifact collision") {
// prompt user to diff/backup the destination, then retry
return handleCollision(err)
}
return err
} Prevention
- Diff source and destination sidecars before running migrate
- Never hand-edit generated sidecar files; keep customizations elsewhere
- Back up hook directories before upgrading bd versions
When it happens
Trigger: Running `bd migrate` when a retire op's destination path exists and filesEqual returns false — i.e. the destination sidecar was customized or written by a different bd version than the source.
Common situations: User hand-edited the destination hook sidecar after an earlier migration; two bd versions with different sidecar templates both installed; a partial previous migration left a stale destination file.
Related errors
- checking destination sidecar %s: %w
- comparing sidecars %s and %s: %w
- checking sidecar %s: %w
- checking sidecar destination %s: %w
- comparing sidecar %s to %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d289475479e5d977.
Report an issue: GitHub.