{"record":{"id":"107eec745d7c0f17","repo":"larksuite/cli","slug":"invalid-cli-token-q","errorCode":null,"errorMessage":"invalid cli token %q","messagePattern":"invalid cli token %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/typed_compile_args.go","lineNumber":524,"sourceCode":"\tif result.minimum != nil && result.maximum != nil && *result.minimum > *result.maximum {\n\t\treturn result, fmt.Errorf(\"minimum exceeds maximum\")\n\t}\n\tif result.minItems != nil && result.maxItems != nil && *result.minItems > *result.maxItems {\n\t\treturn result, fmt.Errorf(\"minItems exceeds maxItems\")\n\t}\n\treturn result, nil\n}\n\nfunc parseCLITag(raw string) (typedCLIInput, error) {\n\tvar result typedCLIInput\n\tif raw == \"\" {\n\t\treturn result, nil\n\t}\n\tseen := make(map[string]struct{})\n\tfor _, token := range strings.Split(raw, \";\") {\n\t\tkey, value, ok := strings.Cut(token, \"=\")\n\t\tif !ok || value == \"\" || token != strings.TrimSpace(token) {\n\t\t\treturn result, fmt.Errorf(\"invalid cli token %q\", token)\n\t\t}\n\t\tif _, duplicate := seen[key]; duplicate {\n\t\t\treturn result, fmt.Errorf(\"cli token %q is duplicated\", key)\n\t\t}\n\t\tseen[key] = struct{}{}\n\t\tswitch key {\n\t\tcase \"sources\":\n\t\t\tfor _, source := range strings.Split(value, \"|\") {\n\t\t\t\tresult.ValueSources = append(result.ValueSources, typedValueSource(source))\n\t\t\t}\n\t\tcase \"encoding\":\n\t\t\tresult.Encoding = typedCLIEncoding(value)\n\t\tdefault:\n\t\t\treturn result, fmt.Errorf(\"unknown cli token %q\", key)\n\t\t}\n\t}\n\treturn result, nil\n}","sourceCodeStart":506,"sourceCodeEnd":542,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/typed_compile_args.go#L506-L542","documentation":"parseCLITag parses the `cli` struct tag's semicolon-separated tokens. Each token must be `key=value`, non-empty on the value side, and free of surrounding whitespace. A token missing '=', with an empty value, or with leading/trailing spaces is rejected with this error at compile time.","triggerScenarios":"Tags like cli:\"sources\" (no =), cli:\"encoding=\" (empty value), or cli:\" encoding=json\" (untrimmed) on a typed shortcut input field.","commonSituations":"Formatting the tag with spaces after semicolons for readability (e.g. \"sources=env; encoding=json\"), forgetting the value, or using the wrong separator order.","solutions":["Write every token as key=value with no spaces around tokens or semicolons.","Provide a non-empty value for every token, e.g. cli:\"encoding=json\".","Remove tokens that need no value; use the schema tag for required/optional style flags."],"exampleFix":"// before\nPayload string `schema:\"required\" cli:\"sources=stdin; encoding=json\"`\n// after\nPayload string `schema:\"required\" cli:\"sources=stdin;encoding=json\"`","handlingStrategy":"validation","validationCode":"func cliTagTokensWellFormed(tag string) bool {\n\tfor _, tok := range strings.Split(tag, \";\") {\n\t\tif tok != strings.TrimSpace(tok) {\n\t\t\treturn false\n\t\t}\n\t\t_, v, ok := strings.Cut(tok, \"=\")\n\t\tif !ok || v == \"\" {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never put spaces after semicolons in the cli tag; the grammar is strict.","Every token must be key=value with a non-empty value.","Copy an existing valid cli tag as a template when adding new fields."],"tags":["go","struct-tags","cli","parsing"],"backgroundTag":"invalid-struct-tag-grammar","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"}