{"record":{"id":"002a5c535d3ecfea","repo":"larksuite/cli","slug":"version-q-has-more-than-three-numeric-components","errorCode":null,"errorMessage":"version %q has more than three numeric components","messagePattern":"version %q has more than three numeric components","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/platform/version.go","lineNumber":132,"sourceCode":"\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}\n\tfor i, f := range fields {\n\t\tn, err := strconv.Atoi(strings.TrimSpace(f))\n\t\tif err != nil || n < 0 {\n\t\t\treturn [3]int{}, fmt.Errorf(\"non-numeric component %q in version %q\", f, s)\n\t\t}\n\t\tparts[i] = n\n\t}\n\treturn parts, nil\n}\n\nfunc compareSemver(a, b [3]int) int {\n\tfor i := 0; i < 3; i++ {\n\t\tif a[i] < b[i] {\n\t\t\treturn -1\n\t\t}\n\t\tif a[i] > b[i] {\n\t\t\treturn 1","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/platform/version.go#L114-L150","documentation":"parseSemverPrefix accepts at most MAJOR.MINOR.PATCH. It throws this error when a version string splits into more than three dot-separated numeric fields. The fail-closed guard prevents a malformed RequiredCLIVersion from passing validation while the comparator operates on truncated (wrong) components.","triggerScenarios":"Calling satisfiesRequiredCLIVersion with a version like \"1.2.3.4\" or \"1.2.3.0.1\" (more than 3 dot-separated components).","commonSituations":"Copying a four-part version from another tool (e.g. Windows-style file versions); typos with extra dots; pasting a full build string with dotted suffixes into the config.","solutions":["Trim the version to three components: \"1.2.3.4\" -> \"1.2.3\".","Express build metadata with '-' or '+' instead of extra dot components, e.g. \"1.2.3-beta.1\".","Verify the RequiredCLIVersion source; a release script may be emitting an internal multi-part build number."],"exampleFix":"// before\nrequiredCLIVersion = \"1.2.3.4\"\n// after\nrequiredCLIVersion = \"1.2.3\"","handlingStrategy":"validation","validationCode":"func isThreePartVersion(s string) bool {\n\ts = strings.TrimPrefix(strings.TrimSpace(s), \"v\")\n\tif i := strings.IndexAny(s, \"-+\"); i >= 0 { s = s[:i] }\n\treturn len(strings.Split(s, \".\")) <= 3 && s != \"\"\n}","typeGuard":"func isSemverPrefix(s string) bool { parts := strings.Split(s, \".\"); return len(parts) >= 1 && len(parts) <= 3 }","tryCatchPattern":"parts, err := parseSemverPrefix(v)\nif err != nil {\n\tif strings.Contains(err.Error(), \"more than three numeric components\") {\n\t\t// trim to first three components or surface a config error\n\t}\n\treturn err\n}","preventionTips":["Keep version fields in MAJOR[.MINOR[.PATCH]] form only.","Convert build metadata to '-'/'+' suffixes, never extra dot components.","Lint release scripts that generate the version field for multi-part numbers."],"tags":["version-parsing","config"],"backgroundTag":"invalid-version-format","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"}