gastownhall/beads · error
got %d close reasons for %d issue IDs; provide exactly one s
Error message
got %d close reasons for %d issue IDs; provide exactly one shared reason or one reason per issue
What it means
resolveCloseReasons validates that when multiple `--reason` flags are supplied to `bd close`, their count must either be 1 (shared reason for all issues) or exactly equal to the number of issue ID arguments. If the counts mismatch, closing is refused to avoid ambiguous reason-to-issue mapping.
Source
Thrown at cmd/bd/close.go:452
if fileReason, ok, err := resolveReasonFile(cmd, len(reasons) > 0); err != nil {
return nil, args, err
} else if ok {
reasons = []string{fileReason}
}
// Desire-path: "bd done <id> <message>" treats last positional arg as reason
// when no reason flag was explicitly provided (hq-pe8ce)
if len(reasons) == 0 && cmd.CalledAs() == "done" && len(args) >= 2 {
reasons = []string{args[len(args)-1]}
args = args[:len(args)-1]
}
if len(reasons) == 0 {
reasons = []string{"Closed"}
}
if len(reasons) > 1 && len(reasons) != len(args) {
return nil, args, fmt.Errorf("got %d close reasons for %d issue IDs; provide exactly one shared reason or one reason per issue", len(reasons), len(args))
}
return reasons, args, nil
}
func collectCloseReasonFlags(cmd *cobra.Command) ([]string, error) {
if flag := cmd.Flags().Lookup("reason"); flag != nil {
if v, ok := flag.Value.(interface{ Values() []string }); ok {
if reasons := nonEmptyCloseReasons(v.Values()); len(reasons) > 0 {
return reasons, nil
}
}
}
for _, name := range []string{"resolution", "message", "comment"} {
reason, err := cmd.Flags().GetString(name)
if err != nil {
return nil, err
}View on GitHub (pinned to 71377f2769)
Solutions
- Supply exactly one --reason to apply it to all issues, or one --reason per issue ID so counts match.
- Count reasons and IDs in your script before invoking bd close.
- Alternatively use --reason-file with a single shared reason text.
Example fix
// before bd close bd-1 bd-2 bd-3 --reason "done" --reason "done" // after bd close bd-1 bd-2 bd-3 --reason "done"
Defensive patterns
Strategy: validation
Validate before calling
if [ $(printf '%s\n' "$@" | grep -c -- '--reason') -gt 1 ]; then # ensure reasons count == issue ids count, else use a single --reason fi
Type guard
func reasonsMatchIDs(reasons, ids []string) bool {
return len(reasons) <= 1 || len(reasons) == len(ids)
} Try / catch
reasons, args, err := resolveCloseReasons(cmd, args)
if err != nil && strings.Contains(err.Error(), "close reasons for") {
// fall back to a single shared reason and retry
} Prevention
- Always use a single --reason in scripts unless intentionally doing per-issue reasons
- Count flags programmatically before invoking bd close
- Prefer --reason-file for shared multi-line reasons
When it happens
Trigger: Calling `bd close` with N issue IDs and more than one --reason flag where the number of reasons != N, e.g. `bd close bd-1 bd-2 bd-3 --reason a --reason b`.
Common situations: Shell scripts building the reason list dynamically; users pasting a partial list of per-issue reasons; forgetting an issue ID in the argument list while providing full per-issue reasons.
Related errors
- cannot specify both --reason-file and --reason/--resolution/
- --reason-file %q is empty; close reason is required
- invalid mode '%s', must be 'compile' or 'runtime'
- runtime mode requires all variables to have values Missing:
- --deps cannot attach both %q and %q to the same target %q: a
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/3e1a12cda7eb5308.
Report an issue: GitHub.