{"record":{"id":"312ca510663c9f58","repo":"gastownhall/beads","slug":"checking-destination-sidecar-s-w","errorCode":null,"errorMessage":"checking destination sidecar %s: %w","messagePattern":"checking destination sidecar (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/migrate_hooks_apply.go","lineNumber":360,"sourceCode":"\t\treturn \"#!/usr/bin/env sh\\n\"\n\t}\n\n\treturn \"#!/usr/bin/env sh\\n\" + trimmedLeading\n}\n\nfunc validateRetireCollisionPolicy(retireOps []hookMigrationRetireOp) error {\n\tfor _, op := range retireOps {\n\t\tsourceExists, err := pathExists(op.SourcePath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"checking source sidecar %s: %w\", op.SourcePath, err)\n\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","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/migrate_hooks_apply.go#L342-L378","documentation":"This error wraps an underlying OS error returned by os.Stat while `bd migrate` checks whether a retire-operation's destination sidecar path already exists, during the pre-apply collision validation pass. It means the filesystem could not be queried at all for the destination path — not that the file exists or doesn't. The migration aborts safely before any changes are applied.","triggerScenarios":"Running `bd migrate` hook application when os.Stat(op.DestinationPath) fails with an error other than os.ErrNotExist — e.g. a permission-denied directory on the destination path, a dangling symlink resolved through an inaccessible parent, or I/O error on the filesystem.","commonSituations":"Destination directory with restrictive permissions (different owner, read-only mount), destination path on a disconnected network mount, or a corrupted/broken symlink chain in the destination directory.","solutions":["Inspect the wrapped error: run `ls -ld` on the destination path and each parent directory to find where access fails.","Fix permissions on the destination directory (chown/chmod) or run the migration as a user with access.","Remove or repair broken symlinks in the destination path.","If the path is on a network/removable mount, remount it and re-run `bd migrate`."],"exampleFix":"// before: destination under a root-owned dir\n$ bd migrate\n// after\n$ sudo chown -R $(whoami) /usr/local/lib/bd/sidecars\n$ bd migrate","handlingStrategy":"validation","validationCode":"dest := op.DestinationPath\nif _, err := os.Stat(filepath.Dir(dest)); err != nil {\n\treturn fmt.Errorf(\"destination dir not accessible: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := validateRetireCollisionPolicy(ops); err != nil {\n\tif pe, ok := err.(*fs.PathError); ok && errors.Is(pe, os.ErrPermission) {\n\t\t// fix permissions or re-run elevated\n\t}\n\treturn err\n}","preventionTips":["Ensure the destination sidecar directory exists with correct ownership before migrating","Avoid running bd migrate against paths on unavailable network mounts","Run bd as the same user that owns the hook directories"],"tags":["filesystem","permissions","migration","go"],"backgroundTag":"permission-denied","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}