larksuite/cli · error

normalize alias --%s cannot declare Conflict

Error message

normalize alias --%s cannot declare Conflict

What it means

Aliases in `normalize` mode rewrite the value into the canonical flag and therefore cannot also declare a Conflict policy (canonical_wins, error_if_both, trimmed_equal_or_error); conflict semantics only apply to `independent` aliases. Declaring both is contradictory and rejected.

Source

Thrown at shortcuts/common/typed_compile_args.go:356

	default:
		return fmt.Errorf("unknown CLI encoding %q", field.cli.Encoding)
	}
	seenAliases := make(map[string]struct{})
	for i, alias := range field.cli.Aliases {
		if !aliasNamePattern.MatchString(alias.Name) {
			return fmt.Errorf("alias[%d] name %q is invalid", i, alias.Name)
		}
		if alias.Name == field.name {
			return fmt.Errorf("alias[%d] duplicates canonical flag --%s", i, field.name)
		}
		if _, duplicate := seenAliases[alias.Name]; duplicate {
			return fmt.Errorf("duplicate alias --%s", alias.Name)
		}
		seenAliases[alias.Name] = struct{}{}
		switch alias.Mode {
		case typedAliasNormalize:
			if alias.Conflict != "" {
				return fmt.Errorf("normalize alias --%s cannot declare Conflict", alias.Name)
			}
			if alias.Deprecated {
				return fmt.Errorf("deprecated alias --%s must use independent mode so Cobra can emit its warning", alias.Name)
			}
		case typedAliasIndependent:
			switch alias.Conflict {
			case typedAliasCanonicalWins, typedAliasErrorIfBoth:
			case typedAliasTrimmedEqualOrError:
				if indirectKind(field.valueType) != reflect.String {
					return fmt.Errorf("trimmed_equal_or_error alias --%s requires string input", alias.Name)
				}
			default:
				return fmt.Errorf("independent alias --%s must declare a supported Conflict", alias.Name)
			}
		default:
			return fmt.Errorf("alias --%s has invalid Mode %q", alias.Name, alias.Mode)
		}
	}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Remove the conflict=... token from the normalize alias tag.
  2. If conflict semantics are required, switch the alias mode to independent and pick a supported Conflict value.
  3. Keep normalize aliases minimal: name and optional deprecation-free usage only (deprecated also requires independent mode).

Example fix

// before
cli:"alias=old-name,mode=normalize,conflict=error_if_both"
// after
cli:"alias=old-name,mode=normalize"
Defensive patterns

Strategy: validation

Validate before calling

func validAliasMode(mode, conflict string) error {
	if mode == "normalize" && conflict != "" {
		return fmt.Errorf("normalize aliases cannot declare conflict")
	}
	return nil
}

Prevention

When it happens

Trigger: cli tag declares an alias with normalize mode plus a conflict clause, e.g. alias=xxx,mode=normalize,conflict=error_if_both; validateInputCLI's typedAliasNormalize branch sees alias.Conflict != "".

Common situations: Copying a full alias tag string (including conflict=...) from an independent alias and only changing the mode; misunderstanding that normalize aliases always merge into the canonical flag so conflict is moot.

Related errors


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