{"record":{"id":"b9644c5694957577","repo":"larksuite/cli","slug":"empty-version","errorCode":null,"errorMessage":"empty version","messagePattern":"empty version","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/platform/version.go","lineNumber":115,"sourceCode":"\tcase strings.HasPrefix(s, \"<=\"):\n\t\treturn \"<=\", strings.TrimSpace(s[2:])\n\tcase strings.HasPrefix(s, \">\"):\n\t\treturn \">\", strings.TrimSpace(s[1:])\n\tcase strings.HasPrefix(s, \"<\"):\n\t\treturn \"<\", strings.TrimSpace(s[1:])\n\tcase strings.HasPrefix(s, \"=\"):\n\t\treturn \"=\", strings.TrimSpace(s[1:])\n\tdefault:\n\t\treturn \"\", s\n\t}\n}\n\n// parseSemverPrefix parses MAJOR[.MINOR[.PATCH]] and drops any pre-release /\n// build suffix. Missing minor / patch default to 0. Accepts a leading \"v\".\nfunc parseSemverPrefix(s string) (parts [3]int, err error) {\n\ts = strings.TrimPrefix(strings.TrimSpace(s), \"v\")\n\tif s == \"\" {\n\t\treturn parts, fmt.Errorf(\"empty version\")\n\t}\n\t// Trim pre-release/build suffix at first '-' or '+'.\n\tfor i, c := range s {\n\t\tif c == '-' || c == '+' {\n\t\t\ts = s[:i]\n\t\t\tbreak\n\t\t}\n\t}\n\tfields := strings.Split(s, \".\")\n\t// Reject `1.2.3.4` and longer instead of silently truncating —\n\t// truncation hides the typo and lets a malformed RequiredCLIVersion\n\t// pass validation while the comparator below operates on the wrong\n\t// components. Build-version parsing has its own fail-open guard\n\t// upstream (see satisfiesRequiredCLIVersion comment about exotic\n\t// build tags), so it stays compatible.\n\tif len(fields) > 3 {\n\t\treturn [3]int{}, fmt.Errorf(\"version %q has more than three numeric components\", s)\n\t}","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/platform/version.go#L97-L133","documentation":"parseSemverPrefix validates a version string like \"1.2.3\" used for RequiredCLIVersion comparison. It throws \"empty version\" when, after trimming whitespace and a leading \"v\", the string is empty. This guard exists so an empty RequiredCLIVersion never silently passes validation or compares as all-zero.","triggerScenarios":"Calling satisfiesRequiredCLIVersion with a configured RequiredCLIVersion that is empty or only whitespace (\"\", \"   \", \"v\"), after TrimPrefix/TrimSpace leaves nothing to parse.","commonSituations":"Config/registry metadata with a missing or blank required_cli_version field; a build/release pipeline that wrote an empty value; hand-edited config where the version was deleted.","solutions":["Set RequiredCLIVersion to a concrete MAJOR[.MINOR[.PATCH]] value, e.g. \"1.2\" or \"2.0.3\".","If the version is optional in your config, omit the field entirely rather than setting it to an empty string.","Check where the version value originates (registry meta, env var, config file) for a truncation or placeholder left blank."],"exampleFix":"// before\nrequiredCLIVersion = \"\"\n// after\nrequiredCLIVersion = \"1.2.0\"","handlingStrategy":"validation","validationCode":"func validRequiredCLIVersion(s string) bool {\n\tt := strings.TrimSpace(strings.TrimPrefix(s, \"v\"))\n\treturn t != \"\"\n}\n// guard: if !validRequiredCLIVersion(cfg.RequiredCLIVersion) { fix config before calling }","typeGuard":"func hasVersion(s string) bool { return strings.TrimSpace(strings.TrimPrefix(s, \"v\")) != \"\" }","tryCatchPattern":"parts, err := parseSemverPrefix(v)\nif err != nil {\n\t// err.Error() == \"empty version\": skip or prompt for a concrete version\n\treturn fmt.Errorf(\"invalid RequiredCLIVersion %q: %w\", v, err)\n}","preventionTips":["Never set RequiredCLIVersion to \"\"; omit the field if not needed.","Validate config at load time and fail fast on blank version fields.","Add a schema/config test asserting a non-empty version string."],"tags":["version-parsing","config"],"backgroundTag":"empty-version-string","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"}