gastownhall/beads · error

agents file name exceeds 255 characters

Error message

agents file name exceeds 255 characters

What it means

ValidateAgentsFile caps the agents file name at 255 characters, matching typical filesystem filename limits, to prevent ENAMETOOLONG errors at write time. Names longer than 255 bytes are rejected up front with this error.

Source

Thrown at internal/config/config.go:1173

func SafeAgentsFile() string {
	name := AgentsFile()
	if err := ValidateAgentsFile(name); err != nil {
		debug.Logf("config: agents.file %q failed validation (%v), using default", name, err)
		return DefaultAgentsFile
	}
	return name
}

// ValidateAgentsFile checks that filename is safe to use as an agents file path.
// It rejects absolute paths, path separators, names longer than 255 characters,
// and non-markdown extensions. This is a pure string validation function — I/O
// checks (e.g. symlink detection) are deferred to the file write layer.
func ValidateAgentsFile(filename string) error {
	if filename == "" {
		return fmt.Errorf("agents file name must not be empty")
	}
	if len(filename) > 255 {
		return fmt.Errorf("agents file name exceeds 255 characters")
	}
	if strings.ContainsAny(filename, "/\\") {
		return fmt.Errorf("agents file must be a simple filename without path separators, got %q", filename)
	}
	ext := strings.ToLower(filepath.Ext(filename))
	if ext != ".md" {
		return fmt.Errorf("agents file must have .md extension, got %q", ext)
	}
	return nil
}

// getConfigList retrieves a list-typed configuration value from config.yaml,
// accepting either the YAML list form (e.g. `types: { custom: [step, wisp] }`)
// or the legacy comma-separated string form (e.g.
// `types.custom = "step,wisp"`). Entries are trimmed; empty entries are
// dropped. The dual-form support is required for project-extension
// types/statuses declared in .beads/config.yaml — see gastownhall/beads#4024.
func getConfigList(key string) []string {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Shorten the filename to 255 characters or fewer.
  2. Strip any directory components and pass only the base name (paths are rejected separately).
  3. If the name is generated, truncate or hash the variable portion to fit the limit.

Example fix

// before
name := "agents-" + longTaskID + "-notes.md" // >255 chars
// after
name := "agents-" + longTaskID[:8] + "-notes.md"
Defensive patterns

Strategy: validation

Validate before calling

const maxNameLen = 255
if len(name) > maxNameLen {
    return fmt.Errorf("agents file name %d > %d chars", len(name), maxNameLen)
}

Try / catch

if err := config.SafeAgentsFile(name); err != nil {
    if strings.Contains(err.Error(), "exceeds 255") {
        return fmt.Errorf("shorten the agents file name (got %d chars)", len(name))
    }
    return err
}

Prevention

When it happens

Trigger: Calling ValidateAgentsFile or SafeAgentsFile with a filename whose length exceeds 255 characters — often from concatenating prefixes, timestamps, or an entire path into the name argument.

Common situations: Generated names built by templates that interpolate long IDs; a user pastes a full path into a setting that expects a bare filename; locale/multibyte names push length over the limit.

Related errors


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