gastownhall/beads · error
failed to read %s: %w
Error message
failed to read %s: %w
What it means
When the target agent file exists, updateAgentFile reads it with os.ReadFile to inspect and update its beads section; a read error is wrapped here. This means an existing agent markdown file could not be read, so the update flow aborts before any modification.
Source
Thrown at cmd/bd/init_agent.go:73
// Replace the beads section with the requested profile.
// EmbeddedDefault() ships with profile:full; swap to the requested profile
// (which defaults to minimal). Also handles legacy markers without profile metadata.
if strings.Contains(newContent, "BEGIN BEADS INTEGRATION") {
if replaced, changed, err := agents.ReplaceSectionWithOpts(newContent, profile, opts); err == nil && changed {
newContent = replaced
}
}
// #nosec G306 - markdown needs to be readable
if err := os.WriteFile(filename, []byte(newContent), 0644); err != nil {
return fmt.Errorf("failed to create %s: %w", filename, err)
}
if verbose {
fmt.Printf(" %s Created %s with agent instructions\n", ui.RenderPass("✓"), filename)
}
return nil
} else if err != nil {
return fmt.Errorf("failed to read %s: %w", filename, err)
}
// File exists - check if it already has our sections
contentStr := string(content)
hasBeads := strings.Contains(contentStr, "BEGIN BEADS INTEGRATION")
if hasBeads {
// Preserve existing full profile when minimal is requested (avoid information loss)
effectiveProfile := profile
existingMeta := agents.ParseMarker(contentStr[strings.Index(contentStr, "<!-- BEGIN BEADS INTEGRATION"):])
if existingMeta != nil && existingMeta.Profile == agents.ProfileFull && profile == agents.ProfileMinimal {
effectiveProfile = agents.ProfileFull
if verbose {
fmt.Printf(" ℹ %s already has full profile; preserving (higher-information) content\n", filename)
}
}
// Update existing section to latest versioned format (upgrades legacy markers)View on GitHub (pinned to 71377f2769)
Solutions
- Check the file's read permissions (ls -l) and fix with chmod/chown
- Verify the path is a regular file, not a directory or broken symlink
- Restore file ownership consistency (e.g. after running as root in a container)
- Remove or relocate the unreadable file so init recreates it
Example fix
// before: AGENTS.md owned by root, mode 600 failed to read AGENTS.md: permission denied // after $ sudo chown $(whoami) AGENTS.md && chmod u+rw AGENTS.md $ bd init
Defensive patterns
Strategy: validation
Validate before calling
[ -f AGENTS.md ] && [ ! -r AGENTS.md ] && { echo "AGENTS.md unreadable" >&2; exit 1; } Try / catch
if err := addAgentsInstructions(...); err != nil && strings.Contains(err.Error(), "failed to read") { log.Fatalf("cannot read agent file: %v", err) } Prevention
- Keep agent files owned and readable by the running user
- Verify paths are regular files, not directories/symlinks
- Normalize ownership after containerized runs as root
- Git-tracked files help detect and restore broken state
When it happens
Trigger: bd init/addAgentsInstructions finding an existing AGENTS.md (or CLAUDE.md etc.) that cannot be read: permission denied, path is actually a directory, or I/O error.
Common situations: File owned by another user with restrictive mode; the path is a broken symlink or directory; read-only bind mounts; stale container state after user changes.
Related errors
- failed to create %s: %w
- failed to update %s: %w
- failed to create .beads directory: %v Permission denied. Ch
- failed to create .beads directory: %w
- failed to set beads.role config: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0ad58e8c7bc84049.
Report an issue: GitHub.