gastownhall/beads · error

failed to read template %s: %w

Error message

failed to read template %s: %w

What it means

updateAgentFile builds new agent-instruction files from a template. When the target file doesn't exist and --agents-template is set, it reads that template file; a read failure (missing file, bad permissions) is wrapped here and aborts creating the agent file. Without a template flag, the embedded default (agents.EmbeddedDefault) is used instead.

Source

Thrown at cmd/bd/init_agent.go:48

}

// updateAgentFile creates or updates an agent instructions file with embedded template content.
// When a beads section already exists (legacy or current), it is updated to the latest
// versioned format so that `bd init` never silently locks in stale sections.
// If the file already has a full profile and a minimal profile is requested, the full
// profile is preserved to avoid information loss.
func updateAgentFile(filename string, verbose bool, templatePath string, profile agents.Profile, opts agents.RenderOpts) error {
	// Check if file exists
	//nolint:gosec // G304: filename validated by config.ValidateAgentsFile or defaulted to AGENTS.md
	content, err := os.ReadFile(filename)
	if os.IsNotExist(err) {
		// File doesn't exist - create from template
		var newContent string
		if templatePath != "" {
			//nolint:gosec // G304: templatePath comes from --agents-template flag
			data, readErr := os.ReadFile(templatePath)
			if readErr != nil {
				return fmt.Errorf("failed to read template %s: %w", templatePath, readErr)
			}
			newContent = string(data)
		} else {
			newContent = agents.EmbeddedDefault()
		}

		// 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)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify the --agents-template path exists and is readable (ls -l / cat the file)
  2. Use an absolute path for --agents-template
  3. Omit --agents-template to use the built-in embedded default template
  4. Check file permissions on the template and working directory

Example fix

// before
bd init --agents-template ./templates/agents.tmpl  # file missing
// after
bd init --agents-template /abs/path/templates/agents.tmpl
# or drop the flag entirely:
bd init
Defensive patterns

Strategy: validation

Validate before calling

if [ -n "$TEMPLATE" ] && [ ! -r "$TEMPLATE" ]; then echo "template unreadable: $TEMPLATE" >&2; exit 1; fi

Try / catch

if err := addAgentsInstructions(...); err != nil && strings.Contains(err.Error(), "failed to read template") { /* fix path or drop --agents-template */ }

Prevention

When it happens

Trigger: bd init (or addAgentsInstructions) run with --agents-template pointing to a nonexistent or unreadable path, in a repo where the target agent markdown (e.g. AGENTS.md) does not yet exist.

Common situations: Typo in --agents-template path; template lives outside the sandbox's allowed mounts; relative path resolved from an unexpected working directory; unreadable permissions on the template.

Related errors


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