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

  1. Check the file's read permissions (ls -l) and fix with chmod/chown
  2. Verify the path is a regular file, not a directory or broken symlink
  3. Restore file ownership consistency (e.g. after running as root in a container)
  4. 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

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


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