gastownhall/beads · error

resolving issue ID %q: %w (to %s multiple labels, pass one c

Error message

resolving issue ID %q: %w (to %s multiple labels, pass one comma-separated argument: bd label %s <issue-id> label1,label2)

What it means

When `bd label add`/`bd label remove` receives multiple issue IDs and one of them fails to resolve to a real issue, resolveLabelIssueIDs wraps the failure and appends a hint telling the caller to use a single comma-separated labels argument (`bd label <sub> <issue-id> label1,label2`) instead. The %w-wrapped underlying error (usually a not-found) is preserved.

Source

Thrown at cmd/bd/label.go:229

//
// Resolution stays a front-door job and does not move behind the role:
// GetRequest.ID and UpdateRequest.IssueID are both exact by contract, for the
// reason those docs give — an affordance that can resolve to a different issue
// than the caller named has no place on a contract two front doors share. This
// is therefore the ONE thing that still forks by route, and it forks on how a
// route reaches the store rather than on what it then does with the answer.
//
// Labels come last on the command line, so when several ID-position args fail
// the caller almost certainly passed labels space-separated ("bd label add
// bd-123 a b c"); the error hints at the comma-separated form instead of
// silently skipping the bad args (bd-vu5kv).
func resolveLabelIssueIDs(ctx context.Context, subcommand string, issueIDs []string) ([]string, error) {
	resolved := make([]string, 0, len(issueIDs))
	for _, id := range issueIDs {
		fullID, err := resolveLabelTarget(ctx, id)
		if err != nil {
			if len(issueIDs) > 1 {
				return nil, fmt.Errorf("resolving issue ID %q: %w (to %s multiple labels, pass one comma-separated argument: bd label %s <issue-id> label1,label2)",
					id, err, subcommand, subcommand)
			}
			return nil, fmt.Errorf("resolving issue ID %q: %w", id, err)
		}
		resolved = append(resolved, fullID)
	}
	return resolved, nil
}

//nolint:dupl // labelAddCmd and labelRemoveCmd are similar but serve different operations
var labelAddCmd = &cobra.Command{
	Use:           "add [issue-id...] [label[,label...]]",
	Short:         "Add one or more labels to one or more issues",
	Long:          "Add labels to issues. Issue IDs come first; the final argument is the label. Pass multiple labels comma-separated: bd label add bd-123 label1,label2",
	Args:          cobra.MinimumNArgs(2),
	SilenceUsage:  true,
	SilenceErrors: true,
	RunE: func(cmd *cobra.Command, args []string) error {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check each issue ID with `bd show <id>` and fix the invalid one.
  2. If you meant multiple labels on one issue, pass them comma-separated on a single argument: bd label add <issue-id> label1,label2.
  3. Re-run listing only valid issue IDs.

Example fix

// before
bd label add bd-999999 bd-123 bug,urgent   // bd-999999 unresolvable
// after
bd label add bd-123 bug,urgent             // one issue, comma-separated labels
Defensive patterns

Strategy: validation

Validate before calling

for id in "${IDS[@]}"; do bd show "$id" >/dev/null || { echo "invalid id: $id" >&2; exit 1; }; done
bd label add "${IDS[0]}" "label1,label2"

Prevention

When it happens

Trigger: `bd label add <bad-id> <other-id> mylabel` (or the remove equivalent) where issueIDs contains >1 entry and resolveLabelTarget fails for one of them — typically a mistyped or deleted issue ID.

Common situations: Bulk-labeling several issues where one ID was truncated, renamed, or belongs to another database; confusing the argument order (passing labels as separate args so they are parsed as issue IDs).

Related errors


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