gastownhall/beads · error

ambiguous: %q matches %d protos: %s Use the ID or a more s

Error message

ambiguous: %q matches %d protos:
  %s
Use the ID or a more specific title

What it means

When resolveProtoIDOrTitle's title search matches multiple protos, it cannot choose for the user. It formats every match as 'ID: Title' and throws the 'ambiguous: ... matches %d protos' error, instructing the caller to use the exact ID or a more specific title. This is an intentional disambiguation guard, not a malfunction.

Source

Thrown at cmd/bd/template.go:309

	if exactMatch != nil {
		return exactMatch.ID, nil
	}

	if len(matches) == 0 {
		return "", fmt.Errorf("no proto found matching %q (by ID or title)", input)
	}

	if len(matches) == 1 {
		return matches[0].ID, nil
	}

	// Multiple matches - show them all for disambiguation
	var matchNames []string
	for _, m := range matches {
		matchNames = append(matchNames, fmt.Sprintf("%s: %s", m.ID, m.Title))
	}
	return "", fmt.Errorf("ambiguous: %q matches %d protos:\n  %s\nUse the ID or a more specific title", input, len(matches), strings.Join(matchNames, "\n  "))
}

// extractVariables finds all {{variable}} patterns in text.
// Handlebars control keywords like "else", "this" are excluded.
func extractVariables(text string) []string {
	matches := variablePattern.FindAllStringSubmatch(text, -1)
	seen := make(map[string]bool)
	var vars []string
	for _, match := range matches {
		if len(match) >= 2 && !seen[match[1]] {
			name := match[1]
			// Skip Handlebars control keywords
			if isHandlebarsKeyword(name) {
				continue
			}
			vars = append(vars, name)
			seen[name] = true
		}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run the command with the proto's exact ID instead of its title.
  2. Use a longer, more specific title substring that matches only one proto.
  3. Rename duplicate protos to distinct titles to prevent future ambiguity.
  4. Delete or consolidate stale duplicate protos.

Example fix

// before
bd mol pour deploy            // ambiguous: matches 3 protos
// after
bd mol pour bd-abc123          // use the exact ID
Defensive patterns

Strategy: fallback

Validate before calling

// disambiguate up front:
matches := filterByName(protos, input)
if len(matches) > 1 { fmt.Println("use exact ID:"); for _, m := range matches { fmt.Println(m.ID, m.Title) } }

Try / catch

pid, err := resolveProtoIDOrTitle(ctx, s, input)
if err != nil && strings.Contains(err.Error(), "ambiguous:") {
	// parse listed matches from err and prompt user to choose an ID
	return err
}

Prevention

When it happens

Trigger: Invoking a proto command with a title string that is a substring/prefix of, or otherwise matches, several template-labeled issues — e.g. two protos titled 'Deploy' and 'Deploy Service'.

Common situations: Generic proto names like 'test' or 'build' colliding across teams; duplicated protos created before a rename; case differences that the fuzzy matcher treats as matches.

Related errors


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