gastownhall/beads · error
commands %q and %q both map to doc page %s.md; rename one
Error message
commands %q and %q both map to doc page %s.md; rename one
What it means
Returned by writeGenericCLIDocsDir when two distinct command names collapse to the same doc page ID via commandDocID (which strips punctuation). This prevents one page silently overwriting the other.
Source
Thrown at cmd/bd/help_all.go:329
if err := os.MkdirAll(outDir, 0o755); err != nil {
return err
}
if err := removeMarkdownFiles(outDir); err != nil {
return err
}
commands := availableCommandNames(root)
if err := writeMarkdownFile(filepath.Join(outDir, "index.md"), genericCLIReferenceIndex(root, commands)); err != nil {
return err
}
// commandDocID collapses punctuation, so distinct command names can map
// to the same page file; the later write would silently win.
seen := make(map[string]string, len(commands))
for _, name := range commands {
id := commandDocID(name)
if prev, ok := seen[id]; ok {
return fmt.Errorf("commands %q and %q both map to doc page %s.md; rename one", prev, name, id)
}
seen[id] = name
var out bytes.Buffer
if err := writeSingleCommandDoc(&out, root, name); err != nil {
return err
}
path := filepath.Join(outDir, id+".md")
if err := writeMarkdownFile(path, out.String()); err != nil {
return err
}
}
return nil
}
func genericCLIReferenceIndex(root *cobra.Command, commands []string) string {
var b strings.BuilderView on GitHub (pinned to 71377f2769)
Solutions
- Rename one of the commands in the docs list so IDs differ, as the message advises.
- Remove the duplicate/alias entry from the commands list if both spellings refer to one command.
- If the collision is inherent, change commandDocID's collapsing rules deliberately (with a test).
Example fix
// before: collision
commands := []string{"mol pour", "mol-pour"}
// after
commands := []string{"mol pour"} Defensive patterns
Strategy: validation
Validate before calling
ids := map[string]string{}
for _, name := range commands {
id := commandDocID(name)
if prev, ok := ids[id]; ok { return fmt.Errorf("doc id collision: %s vs %s", prev, name) }
ids[id] = name
} Try / catch
if err := writeGenericCLIDocsDir(...); err != nil {
if strings.Contains(err.Error(), "both map to doc page") {
// dedupe command list and retry
}
} Prevention
- Keep only one spelling per command in the docs list.
- Add a unit test asserting commandDocID uniqueness across all commands.
- Review punctuation-sensitive naming when adding command aliases.
When it happens
Trigger: The commands list passed to writeGenericCLIDocsDir contains two names whose commandDocID values are equal (e.g. 'mol pour' and 'mol-pour' or 'mol.pour' both mapping to 'mol-pour.md'); the second hit of a seen id triggers the error.
Common situations: Adding a new alias or renamed command to the docs list without removing the old spelling, punctuation-only differences between command names, or duplicate entries in a generated commands list.
Related errors
- Error: command not found: %s
- ErrAmbiguousID
- 'bd admin %s' is not yet supported in embedded mode
- cannot use multiple conflict resolution flags
- cannot use both --pull-only and --push-only
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d99b9ed8f3e7fa50.
Report an issue: GitHub.