{"record":{"id":"d289475479e5d977","repo":"gastownhall/beads","slug":"artifact-collision-for-s-s-already-exists-with","errorCode":null,"errorMessage":"artifact collision for %s: %s already exists with different content","messagePattern":"artifact collision for (.+?): (.+?) already exists with different content","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/migrate_hooks_apply.go","lineNumber":371,"sourceCode":"\t\t}\n\t\tif !sourceExists {\n\t\t\tcontinue\n\t\t}\n\n\t\tdestinationExists, err := pathExists(op.DestinationPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"checking destination sidecar %s: %w\", op.DestinationPath, err)\n\t\t}\n\t\tif !destinationExists {\n\t\t\tcontinue\n\t\t}\n\n\t\tequal, err := filesEqual(op.SourcePath, op.DestinationPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"comparing sidecars %s and %s: %w\", op.SourcePath, op.DestinationPath, err)\n\t\t}\n\t\tif !equal {\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"artifact collision for %s: %s already exists with different content\",\n\t\t\t\top.SourcePath,\n\t\t\t\top.DestinationPath,\n\t\t\t)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc retireHookSidecar(op hookMigrationRetireOp) (string, error) {\n\tsourceExists, err := pathExists(op.SourcePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"checking sidecar %s: %w\", op.SourcePath, err)\n\t}\n\tif !sourceExists {\n\t\treturn \"\", nil\n\t}","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/migrate_hooks_apply.go#L353-L389","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n$ diff ~/.bd/hooks/old.sh ~/.bd/hooks/new.sh   # differs\n// after\n$ mv ~/.bd/hooks/new.sh ~/.bd/hooks/new.sh.bak\n$ bd migrate   # completes; source content wins","handlingStrategy":"validation","validationCode":"if same, _ := filesEqual(src, dst); !same {\n\tfmt.Printf(\"collision: %s differs from %s; back up or merge first\\n\", src, dst)\n\tos.Exit(1)\n}","typeGuard":null,"tryCatchPattern":"if err := validateRetireCollisionPolicy(ops); err != nil {\n\tif strings.Contains(err.Error(), \"artifact collision\") {\n\t\t// prompt user to diff/backup the destination, then retry\n\t\treturn handleCollision(err)\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["collision","migration","conflict","go"],"backgroundTag":"artifact-collision","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}