{"record":{"id":"9d551317ff2e8424","repo":"gastownhall/beads","slug":"reading-hook-file-w","errorCode":null,"errorMessage":"reading hook file: %w","messagePattern":"reading hook file: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/hooks.go","lineNumber":599,"sourceCode":"\t\t\tafter = strings.TrimPrefix(after, \"v\")\n\t\t\tafter = strings.TrimSuffix(after, \"---\")\n\t\t\tversion := strings.TrimSpace(after)\n\t\t\treturn hookVersionInfo{Version: version, IsShim: true, IsBdHook: true}, nil\n\t\t}\n\t\t// Check for thin shim marker first\n\t\tif strings.HasPrefix(line, shimVersionPrefix) {\n\t\t\tversion := strings.TrimSpace(strings.TrimPrefix(line, shimVersionPrefix))\n\t\t\treturn hookVersionInfo{Version: version, IsShim: true, IsBdHook: true}, nil\n\t\t}\n\t\t// Check for legacy version marker\n\t\tif strings.HasPrefix(line, hookVersionPrefix) {\n\t\t\tversion := strings.TrimSpace(strings.TrimPrefix(line, hookVersionPrefix))\n\t\t\treturn hookVersionInfo{Version: version, IsShim: false, IsBdHook: true}, nil\n\t\t}\n\t}\n\n\tif err := scanner.Err(); err != nil {\n\t\treturn hookVersionInfo{}, fmt.Errorf(\"reading hook file: %w\", err)\n\t}\n\n\t// Check if it's an inline bd hook (from bd init) - GH#1120\n\t// These don't have version markers but have \"# bd (beads)\" comment\n\tif strings.Contains(content.String(), inlineHookMarker) {\n\t\treturn hookVersionInfo{IsBdHook: true}, nil\n\t}\n\n\t// No version found and not a bd hook\n\treturn hookVersionInfo{}, nil\n}\n\n// FormatHookWarnings returns a formatted warning message if hooks are outdated\nfunc FormatHookWarnings(statuses []HookStatus) string {\n\tvar warnings []string\n\n\tmissingCount := 0\n\toutdatedCount := 0","sourceCodeStart":581,"sourceCodeEnd":617,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/hooks.go#L581-L617","documentation":"Wraps a scanner error encountered while reading a git hook file line-by-line in getHookVersion. It indicates the hook file could not be fully read (I/O error), not that its version is unknown. The wrapped cause identifies the read failure.","triggerScenarios":"scanner.Err() is non-nil after scanning the hook file during getHookVersion, called from CheckGitHooks, isBdOwnedHookFile, installHooksWithOptions, uninstallHooks, or runChainedHook.","commonSituations":"Hook file permissions deny reading (permission denied), the file is deleted/truncated mid-scan, disk I/O errors, or a file replaced by a FIFO/device that errors on read.","solutions":["Fix file permissions on .git/hooks/<hook> (chmod u+r or re-own the file).","Remove the broken hook file and re-run bd init / bd hooks install to reinstall it.","Check disk/filesystem health if the wrapped cause indicates I/O errors."],"exampleFix":"// before\n$ bd hooks install\n// error: reading hook file: open .git/hooks/pre-commit: permission denied\n// after\n$ chmod u+r .git/hooks/pre-commit  # or: rm -f .git/hooks/pre-commit\n$ bd hooks install","handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(hookPath); err != nil || !fi.Mode().IsRegular() {\n\treturn errors.New(\"hook file unreadable or not a regular file\")\n}","typeGuard":null,"tryCatchPattern":"info, err := getHookVersion(hookPath)\nif err != nil && strings.HasPrefix(err.Error(), \"reading hook file:\") {\n\t// fall back to treating the hook as unknown/foreign\n}","preventionTips":["Keep .git/hooks files owned and readable by the repo user.","Avoid FIFOs/devices or exotic files at hook paths.","Reinstall hooks via bd init if a hook file looks broken."],"tags":["git-hooks","file-io","permissions","wrapped-error"],"backgroundTag":"hook-file-read-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}