{"record":{"id":"65f69fcaa65bc313","repo":"hashicorp/terraform","slug":"os-portion-must-not-contain-whitespace","errorCode":null,"errorMessage":"OS portion must not contain whitespace","messagePattern":"OS portion must not contain whitespace","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getproviders/types.go","lineNumber":123,"sourceCode":"\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//\n// If attempting to install providers for use on the same system where the\n// installation process is running, this is the right platform to use.\nvar CurrentPlatform = Platform{\n\tOS:   runtime.GOOS,\n\tArch: runtime.GOARCH,","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/getproviders/types.go#L105-L141","documentation":"Returned by ParsePlatform (internal/getproviders/types.go:123) when the OS segment (the part before the underscore) contains any of space/tab/newline/CR, detected via strings.ContainsAny(os, \" \\t\\n\\r\"). It guards against platform identifiers that have the right underscore count but a polluted OS component that would later break filesystem paths or registry lookups.","triggerScenarios":"Calling ParsePlatform on a string like \"lin ux_amd64\", \"linux\\tamd64\", or a value read from a config/lock file that got line-break contamination (e.g. a value spanning two lines).","commonSituations":"Copy-paste of platform identifiers with stray spaces, values ingested from CSV/YAML that retained trailing whitespace, Windows CR/LF line endings leaking into a Linux-built binary's runtime.GOOS-derived string, or shell word-splitting bugs that inject spaces.","solutions":["Trim surrounding/internal whitespace from the input before calling ParsePlatform, or reject it.","Source the OS portion from runtime.GOOS / a controlled constant rather than free-form text.","Validate with regexp ^\\S+$ against the OS segment before parsing.","Sanitize config readers (CSV parsers, file reads) for stray tabs/newlines."],"exampleFix":"// before\np, err := ParsePlatform(\"lin ux_amd64\")  // -> OS portion must not contain whitespace\n\n// after\nstr := strings.TrimSpace(rawStr)\nstr = strings.Map(func(r rune) rune {\n    if r == ' ' || r == '\\t' || r == '\\n' || r == '\\r' { return -1 }\n    return r\n}, str)\np, err := ParsePlatform(str)","handlingStrategy":"validation","validationCode":"func cleanPlatformString(s string) string {\n    return strings.Map(func(r rune) rune {\n        if r == ' ' || r == '\\t' || r == '\\n' || r == '\\r' { return -1 }\n        return r\n    }, s)\n}\n// then ParsePlatform(cleanPlatformString(raw))","typeGuard":"func osSegmentClean(s string) bool {\n    parts := strings.SplitN(s, \"_\", 2)\n    if len(parts) != 2 { return false }\n    return !strings.ContainsAny(parts[0], \" \\t\\n\\r\")\n}","tryCatchPattern":"p, err := getproviders.ParsePlatform(raw)\nif err != nil && strings.Contains(err.Error(), \"OS portion\") {\n    raw = cleanPlatformString(raw)\n    p, err = getproviders.ParsePlatform(raw)\n}","preventionTips":["Always strings.TrimSpace config-sourced strings before parsing.","Source OS from runtime.GOOS or a constant, not free text.","Validate segments against ^\\S+$ at the boundary.","Scan config files for stray tabs/newlines during ingestion."],"tags":["platform","parsing","provider","validation","whitespace"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}