gastownhall/beads · error
close reason is empty or default; provide a summary of what
Error message
close reason is empty or default; provide a summary of what was done
What it means
ValidateCloseReason refuses close reasons that are empty or exactly the word "closed" (case-insensitive). The library requires a human-meaningful summary of what was done when closing an issue, because validation.on-close config enforces close-reason quality. A bare or default reason carries no audit value.
Source
Thrown at internal/validation/template.go:208
heading := strings.ToLower(strings.TrimPrefix(m.Heading, "## "))
if heading == "acceptance criteria" || heading == "success criteria" {
continue // satisfied by the dedicated field
}
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
- Pass a descriptive reason with the close command, e.g. bd close bd-42 --reason "Fixed by normalizing prefix in bootstrap; covered by tests"
- If closing many issues in a script, template a reason that names the commit or change
- Remove or relax the validation.on-close config only if your team genuinely does not require close summaries
Example fix
// before bd close bd-42 --reason "closed" // after bd close bd-42 --reason "Fixed flaky TestSync by retrying dolt push; see commit ab12cd"
Defensive patterns
Strategy: validation
Validate before calling
func validCloseReason(r string) bool {
r = strings.TrimSpace(r)
return r != "" && !strings.EqualFold(r, "closed") && len(r) >= 20
}
// call: if !validCloseReason(reason) { reason = buildDescriptiveReason() } Try / catch
if err := validation.ValidateCloseReason(reason); err != nil {
if strings.Contains(err.Error(), "empty or default") { reason = promptForReason() }
return err
} Prevention
- Always pass --reason with bd close; never rely on defaults
- Ban the literal "closed" as a reason in scripts and templates
- Enforce a minimum reason length in your own tooling before calling close
When it happens
Trigger: Calling bd close (or any path that invokes ValidateCloseReason via validation.on-close) with an empty --reason flag, whitespace-only input, or the literal string "closed"/"Closed".
Common situations: Scripts and agents closing issues programmatically with bd close without --reason; interactive users accepting a default close message; CI automations that forgot the reason field.
Related errors
- close reason is terse (%d chars); aim for 20+ characters des
- no store is open for this workspace
- not found
- no absolute native user directory is available
- ExternalDoltConfig: set either Socket OR (Host, Port), not b
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/497f3b5c43552849.
Report an issue: GitHub.