{"record":{"id":"2105af4645157839","repo":"hashicorp/terraform","slug":"must-be-two-words-separated-by-an-underscore","errorCode":null,"errorMessage":"must be two words separated by an underscore","messagePattern":"must be two words separated by an underscore","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getproviders/types.go","lineNumber":118,"sourceCode":"// The ordering is lexical first by OS and then by Architecture.\n// This ordering is primarily just to ensure that results of\n// functions in this package will be deterministic. The ordering is not\n// intended to have any semantic meaning and is subject to change in future.\nfunc (p Platform) LessThan(other Platform) bool {\n\tswitch {\n\tcase p.OS != other.OS:\n\t\treturn p.OS < other.OS\n\tdefault:\n\t\treturn p.Arch < other.Arch\n\t}\n}\n\n// ParsePlatform parses a string representation of a platform, like\n// \"linux_amd64\", or returns an error if the string is not valid.\nfunc ParsePlatform(str string) (Platform, error) {\n\tparts := strings.Split(str, \"_\")\n\tif len(parts) != 2 {\n\t\treturn Platform{}, fmt.Errorf(\"must be two words separated by an underscore\")\n\t}\n\n\tos, arch := parts[0], parts[1]\n\tif strings.ContainsAny(os, \" \\t\\n\\r\") {\n\t\treturn Platform{}, fmt.Errorf(\"OS portion must not contain whitespace\")\n\t}\n\tif strings.ContainsAny(arch, \" \\t\\n\\r\") {\n\t\treturn Platform{}, fmt.Errorf(\"architecture portion must not contain whitespace\")\n\t}\n\n\treturn Platform{\n\t\tOS:   os,\n\t\tArch: arch,\n\t}, nil\n}\n\n// CurrentPlatform is the platform where the current program is running.\n//","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/getproviders/types.go#L100-L136","documentation":"Returned by ParsePlatform (internal/getproviders/types.go:118) when the input string does not split into exactly two parts on underscore. ParsePlatform expects the canonical provider-target form OS_ARCH (e.g. linux_amd64); strings with zero underscores, two or more underscores, or a trailing/leading underscore all fail because strings.Split(str, \"_\") yields a slice whose length is not 2.","triggerScenarios":"Calling ParsePlatform with a bare OS (\"linux\"), an arch-only string (\"amd64\"), a triple-segment string (\"linux_amd64_v1\"), or a malformed value derived from user input / lock file / mirror directory name.","commonSituations":"Hand-constructed platform strings for provider mirror layout, corrupted .terraform.lock.hcl, custom tooling that builds target identifiers from GOOS/GOARCH with a wrong separator, or data sourced from a config field that users typed without the underscore.","solutions":["Construct the platform string as OS + \"_\" + ARCH using the two components rather than assembling by hand.","Prefer using getproviders.CurrentPlatform (runtime.GOOS + runtime.GOARCH) instead of parsing a literal.","Validate the string matches regexp ^[^_\\s]+_[^_\\s]+$ before calling ParsePlatform.","If parsing user/config input, normalize or reject early with a clear message."],"exampleFix":"// before\nplatform, err := ParsePlatform(\"linux\")  // len(parts)==1 -> error\n\n// after\nplatform, err := ParsePlatform(\"linux_amd64\")\n// or\nplatform := getproviders.CurrentPlatform","handlingStrategy":"validation","validationCode":"var platformRe = regexp.MustCompile(`^[^_\\s]+_[^_\\s]+$`)\nfunc safeParsePlatform(s string) (getproviders.Platform, error) {\n    if !platformRe.MatchString(s) {\n        return getproviders.Platform{}, fmt.Errorf(\"%q is not OS_ARCH\", s)\n    }\n    return getproviders.ParsePlatform(s)\n}","typeGuard":"func isPlausiblePlatform(s string) bool {\n    parts := strings.Split(s, \"_\")\n    return len(parts) == 2 && parts[0] != \"\" && parts[1] != \"\"\n}","tryCatchPattern":"p, err := getproviders.ParsePlatform(str)\nif err != nil {\n    // fall back to runtime platform or return a clear error\n    p = getproviders.CurrentPlatform\n}","preventionTips":["Build platform strings from OS + \"_\" + ARCH, never hand-typed.","Prefer getproviders.CurrentPlatform when targeting the local host.","Validate with a regex before parsing external/config input.","Reject malformed values at the trust boundary, not deep in install logic."],"tags":["platform","parsing","provider","validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}