larksuite/cli · error

cli token %q is duplicated

Error message

cli token %q is duplicated

What it means

parseCLITag validates the semicolon-delimited `cli:"..."` struct tag grammar for typed input fields. Each token (key=value) may appear at most once; this error fires when the same key is repeated, e.g. two `encoding=` tokens. It is a build-time declaration error caught when the command set is compiled/registered, so a bad tag fails fast instead of silently ignoring the second value.

Source

Thrown at shortcuts/common/typed_compile_args.go:527

	if result.minItems != nil && result.maxItems != nil && *result.minItems > *result.maxItems {
		return result, fmt.Errorf("minItems exceeds maxItems")
	}
	return result, nil
}

func parseCLITag(raw string) (typedCLIInput, error) {
	var result typedCLIInput
	if raw == "" {
		return result, nil
	}
	seen := make(map[string]struct{})
	for _, token := range strings.Split(raw, ";") {
		key, value, ok := strings.Cut(token, "=")
		if !ok || value == "" || token != strings.TrimSpace(token) {
			return result, fmt.Errorf("invalid cli token %q", token)
		}
		if _, duplicate := seen[key]; duplicate {
			return result, fmt.Errorf("cli token %q is duplicated", key)
		}
		seen[key] = struct{}{}
		switch key {
		case "sources":
			for _, source := range strings.Split(value, "|") {
				result.ValueSources = append(result.ValueSources, typedValueSource(source))
			}
		case "encoding":
			result.Encoding = typedCLIEncoding(value)
		default:
			return result, fmt.Errorf("unknown cli token %q", key)
		}
	}
	return result, nil
}

func parseFiniteFloat(value string) (float64, error) {
	return parseFiniteFloatBits(value, 64)

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Remove the duplicated token so each key appears at most once in the cli tag
  2. If you intended multiple sources, use the pipe separator within a single sources token, e.g. sources=a|b
  3. Run the command's compile/startup test (or `go test` on the shortcut package) to confirm the tag parses

Example fix

// before
Field string `cli:"encoding=json;encoding=text"`
// after
Field string `cli:"encoding=json"`
Defensive patterns

Strategy: validation

Validate before calling

func validateCLITagKeys(raw string) error {
	seen := map[string]bool{}
	for _, tok := range strings.Split(raw, ";") {
		key, _, ok := strings.Cut(tok, "=")
		if !ok || key == "" { return fmt.Errorf("bad token %q", tok) }
		if seen[key] { return fmt.Errorf("duplicate cli key %q", key) }
		seen[key] = true
	}
	return nil
}

Prevention

When it happens

Trigger: Declaring a struct field whose `cli` tag repeats a key, e.g. `cli:"sources=a|b;encoding=json;encoding=text"`. parseCLITag splits on ';', cuts on '=', and rejects any key already present in the seen-set.

Common situations: Copy-pasting a cli tag and forgetting to remove a token; merging two field definitions or rebasing branches where both sides added a token; hand-editing generated or documented tag examples.

Related errors


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