{"record":{"id":"1f844ad5cac1989b","repo":"larksuite/cli","slug":"s-alias-s-maps-to-both-s-and-s-after-nor","errorCode":null,"errorMessage":"%s alias --%s maps to both --%s and --%s after normalization to --%s","messagePattern":"(.+?) alias --(.+?) maps to both --(.+?) and --(.+?) after normalization to --(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/flagalias/flagalias.go","lineNumber":112,"sourceCode":"\t\t\t}\n\t\t\tnormalized := normalize(alias)\n\t\t\tif normalized == \"\" {\n\t\t\t\treturn fmt.Errorf(\"%s alias --%s for --%s normalizes to an empty name\", cmd.CommandPath(), alias, canonical)\n\t\t\t}\n\t\t\tif normalized == canonical {\n\t\t\t\treturn fmt.Errorf(\"%s declares --%s as an alias of itself (--%s after normalization)\", cmd.CommandPath(), alias, canonical)\n\t\t\t}\n\t\t\tif existing, ok := registered[normalized]; ok {\n\t\t\t\treturn fmt.Errorf(\"%s alias --%s for --%s conflicts with registered flag --%s after normalization\", cmd.CommandPath(), alias, canonical, existing)\n\t\t\t}\n\t\t\tif existing, ok := acceptedAliases[normalized]; ok {\n\t\t\t\treturn fmt.Errorf(\"%s alias --%s for --%s conflicts with existing alias for --%s after normalization to --%s\", cmd.CommandPath(), alias, canonical, existing, normalized)\n\t\t\t}\n\t\t\tif existing, ok := aliases[normalized]; ok {\n\t\t\t\tif existing == canonical {\n\t\t\t\t\treturn fmt.Errorf(\"%s declares duplicate alias --%s for --%s after normalization to --%s\", cmd.CommandPath(), alias, canonical, normalized)\n\t\t\t\t}\n\t\t\t\treturn fmt.Errorf(\"%s alias --%s maps to both --%s and --%s after normalization to --%s\", cmd.CommandPath(), alias, existing, canonical, normalized)\n\t\t\t}\n\t\t\taliases[normalized] = canonical\n\t\t\tmetadata[canonicalFlag] = append(metadata[canonicalFlag], alias)\n\t\t}\n\t}\n\n\tif len(aliases) == 0 {\n\t\treturn nil\n\t}\n\ttracked := make(map[string]*trackedValue, len(canonicalFlags))\n\tfor canonical, flag := range canonicalFlags {\n\t\ttracked[canonical] = ensureTrackedValue(flag)\n\t}\n\tfor flag, names := range metadata {\n\t\tsetAliases(flag, append(Aliases(flag), names...))\n\t}\n\tflagSet.SetNormalizeFunc(func(set *pflag.FlagSet, name string) pflag.NormalizedName {\n\t\tnormalized := name","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/flagalias/flagalias.go#L94-L130","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pick distinct alias strings so each normalized name maps to only one canonical flag","Delete the alias belonging to the deprecated canonical flag","Unify the two canonical flags into one if they represent the same concept","Bind the alias groups on separate commands/subcommands"],"exampleFix":"// before\nBind(cmd, Alias(\"dryRun\", \"DryRun\"), Alias(\"dry-run\", \"DryRunAll\")) // normalizer folds dashes\n// after\nBind(cmd, Alias(\"dryRun\", \"DryRun\"), Alias(\"dryRunAll\", \"DryRunAll\"))","handlingStrategy":"validation","validationCode":"func checkOneToOne(aliases []flagalias.Alias, norm func(string) string) error {\n\tm := map[string]string{}\n\tfor _, a := range aliases {\n\t\tn := norm(a.Alias)\n\t\tif prev, ok := m[n]; ok && prev != a.Canonical {\n\t\t\treturn fmt.Errorf(\"alias %q maps to both %s and %s\", n, prev, a.Canonical)\n\t\t}\n\t\tm[n] = a.Canonical\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"if err := flagalias.MustBind(cmd, aliases...); err != nil {\n\tif strings.Contains(err.Error(), \"maps to both\") {\n\t\treturn fmt.Errorf(\"alias maps to multiple canonical flags: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Keep a one-normalized-alias-to-one-canonical invariant in the alias table","Remove aliases of deprecated flags when renaming canonical flags","Verify mappings with a unit test that mirrors Bind's normalization"],"tags":["go","cli","flag-alias","duplicate-registration"],"backgroundTag":"flag-alias-conflict","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}