larksuite/cli · error

%s alias --%s maps to both --%s and --%s after normalization

Error message

%s alias --%s maps to both --%s and --%s after normalization to --%s

What it means

Bind rejects an alias whose normalized name is already bound to a different canonical flag within the same command; the alias would map to two canonical flags at once. This is distinct from the registered-flag conflict: here the name collides with a previously accepted alias, not a native flag. The message lists both canonical targets and the shared normalized name for diagnosis.

Source

Thrown at internal/flagalias/flagalias.go:112

			}
			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...))
	}
	flagSet.SetNormalizeFunc(func(set *pflag.FlagSet, name string) pflag.NormalizedName {
		normalized := name

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Pick distinct alias strings so each normalized name maps to only one canonical flag
  2. Delete the alias belonging to the deprecated canonical flag
  3. Unify the two canonical flags into one if they represent the same concept
  4. Bind the alias groups on separate commands/subcommands

Example fix

// before
Bind(cmd, Alias("dryRun", "DryRun"), Alias("dry-run", "DryRunAll")) // normalizer folds dashes
// after
Bind(cmd, Alias("dryRun", "DryRun"), Alias("dryRunAll", "DryRunAll"))
Defensive patterns

Strategy: validation

Validate before calling

func checkOneToOne(aliases []flagalias.Alias, norm func(string) string) error {
	m := map[string]string{}
	for _, a := range aliases {
		n := norm(a.Alias)
		if prev, ok := m[n]; ok && prev != a.Canonical {
			return fmt.Errorf("alias %q maps to both %s and %s", n, prev, a.Canonical)
		}
		m[n] = a.Canonical
	}
	return nil
}

Try / catch

if err := flagalias.MustBind(cmd, aliases...); err != nil {
	if strings.Contains(err.Error(), "maps to both") {
		return fmt.Errorf("alias maps to multiple canonical flags: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Within one Bind call or successive Bind calls on the same command, two aliases with the same normalized form point at different canonical flags, e.g. Alias("dryRun","DryRun") and Alias("dry-run","DryRunAll") where the normalizer converts dashes, so aliases[normalized] exists with existing != canonical.

Common situations: Auto-generated alias sets from two flag families that share naming; renaming a canonical flag and adding an alias that collides with an old family's alias; normalizer introduction in an upgrade that newly merges names.

Related errors


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