larksuite/cli · error

%s declares duplicate alias --%s for --%s after normalizatio

Error message

%s declares duplicate alias --%s for --%s after normalization to --%s

What it means

Bind rejects declaring the exact same alias twice for the same canonical flag once names are normalized. The mapping is already recorded in aliases[normalized] = canonical, so a repeated declaration is redundant and treated as a configuration mistake rather than silently ignored. The error names the command, the duplicated alias, the canonical flag, and the normalized form.

Source

Thrown at internal/flagalias/flagalias.go:110

			if err := validateAliasName(alias); err != nil {
				return fmt.Errorf("%s alias for --%s: %w", cmd.CommandPath(), canonical, err)
			}
			normalized := normalize(alias)
			if normalized == "" {
				return fmt.Errorf("%s alias --%s for --%s normalizes to an empty name", cmd.CommandPath(), alias, canonical)
			}
			if normalized == canonical {
				return fmt.Errorf("%s declares --%s as an alias of itself (--%s after normalization)", cmd.CommandPath(), alias, canonical)
			}
			if existing, ok := registered[normalized]; ok {
				return fmt.Errorf("%s alias --%s for --%s conflicts with registered flag --%s after normalization", cmd.CommandPath(), alias, canonical, existing)
			}
			if existing, ok := acceptedAliases[normalized]; ok {
				return fmt.Errorf("%s alias --%s for --%s conflicts with existing alias for --%s after normalization to --%s", cmd.CommandPath(), alias, canonical, existing, normalized)
			}
			if existing, ok := aliases[normalized]; ok {
				if existing == canonical {
					return fmt.Errorf("%s declares duplicate alias --%s for --%s after normalization to --%s", cmd.CommandPath(), alias, canonical, normalized)
				}
				return fmt.Errorf("%s alias --%s maps to both --%s and --%s after normalization to --%s", cmd.CommandPath(), alias, existing, canonical, normalized)
			}
			aliases[normalized] = canonical
			metadata[canonicalFlag] = append(metadata[canonicalFlag], alias)
		}
	}

	if len(aliases) == 0 {
		return nil
	}
	tracked := make(map[string]*trackedValue, len(canonicalFlags))
	for canonical, flag := range canonicalFlags {
		tracked[canonical] = ensureTrackedValue(flag)
	}
	for flag, names := range metadata {
		setAliases(flag, append(Aliases(flag), names...))
	}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Remove the duplicate alias entry from the list passed to Bind
  2. Deduplicate the alias configuration before binding (e.g. with a map keyed by normalized name)
  3. If the duplicate comes from merging configs, make the merge idempotent

Example fix

// before
Bind(cmd, Alias("verbose", "Verbose"), Alias("verbose", "Verbose"))
// after
Bind(cmd, Alias("verbose", "Verbose"))
Defensive patterns

Strategy: validation

Validate before calling

func dedupeAliases(aliases []flagalias.Alias, norm func(string) string) []flagalias.Alias {
	seen := map[string]bool{}
	out := aliases[:0]
	for _, a := range aliases {
		k := norm(a.Alias) + "->" + a.Canonical
		if !seen[k] { seen[k] = true; out = append(out, a) }
	}
	return out
}

Try / catch

if err := flagalias.MustBind(cmd, aliases...); err != nil {
	if strings.Contains(err.Error(), "declares duplicate alias") {
		return fmt.Errorf("remove duplicate alias entries: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: An alias list passed to Bind (or accumulated across calls to Bind on the same command) contains the same alias string twice for one canonical flag, e.g. Alias("verbose","Verbose") appearing twice, or "Verbose" and "verbose" under a lowercasing normalizer.

Common situations: Merging alias configs from multiple sources without deduplication; copy-paste in a large alias table; version changes that add an alias already present.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/c04fb009609b6ed9. Report an issue: GitHub.