{"record":{"id":"4fb009bc64336c25","repo":"gastownhall/beads","slug":"checking-source-sidecar-s-w","errorCode":null,"errorMessage":"checking source sidecar %s: %w","messagePattern":"checking source sidecar (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/migrate_hooks_apply.go","lineNumber":352,"sourceCode":"\nfunc ensureHookShebang(content string) string {\n\tif strings.HasPrefix(content, \"#!\") {\n\t\treturn content\n\t}\n\n\ttrimmedLeading := strings.TrimLeft(content, \"\\n\")\n\tif trimmedLeading == \"\" {\n\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 {","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/migrate_hooks_apply.go#L334-L370","documentation":"validateRetireCollisionPolicy checks each retire op: if the source sidecar still exists, its content is compared to the destination before retiring. This error wraps a failure of pathExists(op.SourcePath) itself — i.e. the existence check could not be performed (I/O or permission error on the parent directory), so the collision policy cannot be evaluated safely.","triggerScenarios":"pathExists returned a non-nil error (not merely 'false') while checking op.SourcePath during applyHookMigrationExecution — e.g. unreadable parent directory, broken mount, or EACCES on stat.","commonSituations":"Hooks directory with restrictive permissions; network/readonly filesystems where stat fails; path removed mid-run by a concurrent process.","solutions":["Check permissions on the hooks directory (`ls -la .git/hooks`, ensure +r/+x for the user)","Verify the filesystem is healthy and mounted read-write","Re-run apply after fixing access; the check is conservative and will pass once stat succeeds","If a concurrent process is mutating the directory, pause it during migration"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// verify the directory is stat-able before applying\nfs.accessSync(hooksDir, fs.constants.R_OK | fs.constants.X_OK);","typeGuard":null,"tryCatchPattern":"if err := apply(...); err != nil && strings.Contains(err.Error(), \"checking source sidecar\") {\n    // fix directory permissions/mount per the wrapped error, then retry\n}","preventionTips":["Keep .git/hooks readable and executable by the migrating user","Avoid network filesystems for hook migration when possible","Pause concurrent processes that touch the hooks directory during migration"],"tags":["filesystem","permissions","stat","git-hooks"],"backgroundTag":"path-stat-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}