{"record":{"id":"aa2d7d5002baa17f","repo":"gastownhall/beads","slug":"writing-migrated-hook-s-w","errorCode":null,"errorMessage":"writing migrated hook %s: %w","messagePattern":"writing migrated hook (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/migrate_hooks_apply.go","lineNumber":265,"sourceCode":"\t}\n\n\tif err := validateRetireCollisionPolicy(execPlan.RetireOps); err != nil {\n\t\treturn hookMigrationApplySummary{}, err\n\t}\n\n\tsummary := hookMigrationApplySummary{\n\t\tWrittenHooks:     make([]string, 0, len(preparedWrites)),\n\t\tRetiredArtifacts: make([]string, 0, len(execPlan.RetireOps)),\n\t\tSkippedArtifacts: make([]string, 0),\n\t}\n\n\tfor _, write := range preparedWrites {\n\t\tif err := guardHookWritePath(write.Path, false); err != nil {\n\t\t\treturn summary, fmt.Errorf(\"refusing to write migrated hook %s: %w\", write.HookName, err)\n\t\t}\n\t\t// #nosec G306 -- git hooks must be executable for Git to run them\n\t\tif err := os.WriteFile(write.Path, write.Content, 0755); err != nil {\n\t\t\treturn summary, fmt.Errorf(\"writing migrated hook %s: %w\", write.Path, err)\n\t\t}\n\t\tsummary.WrittenHooks = append(summary.WrittenHooks, write.HookName)\n\t}\n\n\tfor _, retire := range execPlan.RetireOps {\n\t\tretired, retiredErr := retireHookSidecar(retire)\n\t\tif retiredErr != nil {\n\t\t\treturn summary, retiredErr\n\t\t}\n\t\tif retired == \"\" {\n\t\t\tsummary.SkippedArtifacts = append(summary.SkippedArtifacts, retire.SourcePath)\n\t\t\tcontinue\n\t\t}\n\t\tsummary.RetiredArtifacts = append(summary.RetiredArtifacts, retired)\n\t}\n\n\tsummary.WrittenHookCount = len(summary.WrittenHooks)\n\tsummary.RetiredCount = len(summary.RetiredArtifacts)","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/migrate_hooks_apply.go#L247-L283","documentation":"After the safety guard passes, bd writes the migrated hook with os.WriteFile (mode 0755, since git hooks must be executable). This error wraps any OS-level write failure — permissions, missing directory, disk full, immutable file — with the hook's path for context.","triggerScenarios":"os.WriteFile(write.Path, write.Content, 0755) returned an error during applyHookMigrationExecution, after guardHookWritePath succeeded.","commonSituations":"Read-only checkout or hooks directory owned by root/another user; worktree on a read-only mount; disk full; path disappeared between guard and write.","solutions":["Fix permissions: `chown` the hooks directory to the current user and ensure it's writable","Check the mount is not read-only (`mount | grep <path>`)","Free disk space if the filesystem is full","Retry `bd migrate hooks apply` once the filesystem condition is fixed"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// verify writability before applying\nfs.accessSync(hooksDir, fs.constants.W_OK);","typeGuard":null,"tryCatchPattern":"if err := apply(...); err != nil && strings.Contains(err.Error(), \"writing migrated hook\") {\n    // inspect wrapped OS error: check permissions, disk space, read-only mount, then retry\n}","preventionTips":["Ensure the repo owner runs the migration (not root/sudo)","Check disk space on read-heavy CI runners","Avoid running migration on read-only mounts"],"tags":["filesystem","permissions","git-hooks","io-error"],"backgroundTag":"file-write-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}