gastownhall/beads · error
close reason is terse (%d chars); aim for 20+ characters des
Error message
close reason is terse (%d chars); aim for 20+ characters describing what was done
What it means
ValidateCloseReason rejects close reasons shorter than 20 characters as too terse. The function trims whitespace, then enforces a minimum length so close summaries actually describe the work performed. This complements the empty/default check and is enforced by validation.on-close config.
Source
Thrown at internal/validation/template.go:211
}
remaining = append(remaining, m)
}
if len(remaining) == 0 {
return nil
}
templateErr.Missing = remaining
return templateErr
}
// ValidateCloseReason checks if a close reason meets minimum quality standards.
// Returns nil if the reason is acceptable. Used by validation.on-close config.
func ValidateCloseReason(reason string) error {
reason = strings.TrimSpace(reason)
if reason == "" || strings.EqualFold(reason, "closed") {
return fmt.Errorf("close reason is empty or default; provide a summary of what was done")
}
if len(reason) < 20 {
return fmt.Errorf("close reason is terse (%d chars); aim for 20+ characters describing what was done", len(reason))
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Write a reason of at least 20 characters describing what was done, e.g. "Closed: implemented X, tested with Y"
- Expand terse script templates to include a short sentence about the change
- Adjust validation.on-close thresholds only if 20 chars is genuinely too strict for your workflow
Example fix
// before bd close bd-42 --reason "done" // after bd close bd-42 --reason "Done: rewrote collector to batch events; 3 tests added"
Defensive patterns
Strategy: validation
Validate before calling
if len(strings.TrimSpace(reason)) < 20 {
return fmt.Errorf("reason must be 20+ chars, got %d", len(strings.TrimSpace(reason)))
} Try / catch
if err := validation.ValidateCloseReason(reason); err != nil {
if strings.HasPrefix(err.Error(), "close reason is terse") { reason = expandReason(reason) }
return err
} Prevention
- Template close reasons as full sentences, not words
- Pre-commit hook or script assertion checking reason length
- Use the close command's summary fields to compose reasons
When it happens
Trigger: Closing an issue with a reason like "done", "ok", "fixed" — any trimmed string of fewer than 20 characters reaching ValidateCloseReason.
Common situations: One-word close messages typed interactively; scripts using placeholder reasons like "wip done"; agents summarizing too briefly.
Related errors
- title must be 500 characters or less
- agents file name exceeds 255 characters
- close reason is empty or default; provide a summary of what
- no store is open for this workspace
- not found
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/45a321e0b815e950.
Report an issue: GitHub.