gastownhall/beads · error

failed to write %s: %w

Error message

failed to write %s: %w

What it means

After composing the new hook content (shebang plus bd section, merged with preserved user content and normalized to LF), bd writes the hook file with os.WriteFile(..., 0755). A failed write aborts installation with this wrapped error. Since bd installs hooks atomically after a pre-flight guard, a failure here is almost always environmental, not logical.

Source

Thrown at cmd/bd/hooks.go:975

					if _, statErr := os.Lstat(backupPath); os.IsNotExist(statErr) {
						// #nosec G306 -- keep executable so a rename restores a working hook
						if backupErr := os.WriteFile(backupPath, existing, 0755); backupErr != nil {
							return fmt.Errorf("failed to back up %s before injecting bd section: %w", hookName, backupErr)
						}
					}
					// Inject section, preserving existing content
					newContent = injectHookSection(existingStr, section)
				}
			}
		}

		// Normalize line endings to LF
		newContent = strings.ReplaceAll(newContent, "\r\n", "\n")

		// Write hook file
		// #nosec G306 -- git hooks must be executable for Git to run them
		if err := os.WriteFile(hookPath, []byte(newContent), 0755); err != nil {
			return fmt.Errorf("failed to write %s: %w", hookName, err)
		}
	}

	// Configure git to use the hooks directory
	if beadsHooks {
		if err := configureBeadsHooksPath(); err != nil {
			return fmt.Errorf("failed to configure git hooks path: %w", err)
		}
	} else if shared {
		if err := configureSharedHooksPath(); err != nil {
			return fmt.Errorf("failed to configure git hooks path: %w", err)
		}
	}

	return nil
}

// preservePreexistingHooks copies non-beads hooks from the currently effective

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix permissions on the hooks directory: `sudo chown -R $(whoami) <hooksDir>`
  2. Free disk space or remount read-only volumes read-write
  3. Check for an external process holding/locking the file and retry
  4. Re-run `bd hooks install` after remediation

Example fix

// before
$ bd hooks install
failed to write pre-commit: permission denied
// after
$ sudo chown $(whoami) .git/hooks && bd hooks install
Defensive patterns

Strategy: validation

Validate before calling

d="$(git rev-parse --git-path hooks 2>/dev/null)"; [ -n "$d" ] && [ -w "$d" ] && [ "$(stat -f %z "$d" 2>/dev/null || echo dir)" ] || echo "check $d writability"

Try / catch

if err := installHooks(...); err != nil { var pe *fs.PathError; if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) { /* free disk, retry */ }; if strings.Contains(err.Error(), "failed to write") { /* fix perms/mount, retry */ } }

Prevention

When it happens

Trigger: os.WriteFile(hookPath, ...) fails during installHooksWithOptions: directory not writable, disk full, read-only mount, or the target was replaced by something unwritable between the guard check and the write (TOCTOU).

Common situations: Root-owned .git/hooks; CI containers with read-only source mounts; full disk; antivirus/backup tools locking files on network filesystems.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/36ddc16e9f97d24d. Report an issue: GitHub.