{"record":{"id":"0b905f369fb84212","repo":"hashicorp/terraform","slug":"invalid-provider-matching-pattern-q-must-have-ei","errorCode":null,"errorMessage":"invalid provider matching pattern %q: must have either two or three slash-separated segments","messagePattern":"invalid provider matching pattern %q: must have either two or three slash-separated segments","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getproviders/multi_source.go","lineNumber":151,"sourceCode":"// The Provider address values in a MultiSourceMatchingPatterns are special in\n// that any of Hostname, Namespace, or Type can be getproviders.Wildcard\n// to indicate that any concrete value is permitted for that segment.\ntype MultiSourceMatchingPatterns []addrs.Provider\n\n// ParseMultiSourceMatchingPatterns parses a slice of strings containing the\n// string form of provider matching patterns and, if all the given strings are\n// valid, returns the corresponding, normalized, MultiSourceMatchingPatterns\n// value.\nfunc ParseMultiSourceMatchingPatterns(strs []string) (MultiSourceMatchingPatterns, error) {\n\tif len(strs) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tret := make(MultiSourceMatchingPatterns, len(strs))\n\tfor i, str := range strs {\n\t\tparts := strings.Split(str, \"/\")\n\t\tif len(parts) < 2 || len(parts) > 3 {\n\t\t\treturn nil, fmt.Errorf(\"invalid provider matching pattern %q: must have either two or three slash-separated segments\", str)\n\t\t}\n\t\thost := defaultRegistryHost\n\t\texplicitHost := len(parts) == 3\n\t\tif explicitHost {\n\t\t\tgivenHost := parts[0]\n\t\t\tif givenHost == \"*\" {\n\t\t\t\thost = svchost.Hostname(Wildcard)\n\t\t\t} else {\n\t\t\t\tnormalHost, err := svchost.ForComparison(givenHost)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"invalid hostname in provider matching pattern %q: %s\", str, err)\n\t\t\t\t}\n\n\t\t\t\t// The remaining code below deals only with the namespace/type portions.\n\t\t\t\thost = normalHost\n\t\t\t}\n\n\t\t\tparts = parts[1:]","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/getproviders/multi_source.go#L133-L169","documentation":"Thrown by ParseMultiSourceMatchingPatterns when a provider matching pattern string splits on '/' into fewer than 2 or more than 3 segments. A pattern must be either 'namespace/type' (2 segments) or 'host/namespace/type' (3 segments); the leading host segment is optional and defaults to the default registry host. Anything else (a bare name, a single segment, four-plus segments, or a leading/trailing slash producing empty parts) is rejected before any hostname/namespace/type normalization runs.","triggerScenarios":"Calling ParseMultiSourceMatchingPatterns (or wiring CLI/config provider_installation include/exclude arrays) with values such as \"aws\", \"hashicorp/aws/extra\", \"a/b/c/d\", \"/aws\", or \"hashicorp/\". The check at multi_source.go:150 is len(parts) < 2 || len(parts) > 3 right after strings.Split(str, \"/\").","commonSituations":"Typos in a .terraformrc / terraform.rc provider_installation block's include/exclude list; copying a full source address like registry.terraform.io/hashicorp/aws and adding an extra path; forgetting the namespace and writing only the type; a stray leading or trailing slash from templating.","solutions":["Rewrite the pattern to exactly two segments (namespace/type, e.g. hashicorp/aws) or three segments (host/namespace/type, e.g. registry.terraform.io/hashicorp/aws).","Remove any leading or trailing slash and any empty middle segment that strings.Split would turn into an extra part.","If you intended a host wildcard, keep three segments and use '*/*/*' (host wildcards force namespace and type wildcards too).","Validate the whole include/exclude slice with ParseMultiSourceMatchingPatterns in a config-load test before deploying."],"exampleFix":"// before\ninclude = [\"aws\"]\nexclude = [\"registry.terraform.io/hashicorp/aws/zip\"]\n\n// after\ninclude = [\"hashicorp/aws\"]\nexclude = [\"registry.terraform.io/hashicorp/aws\"]","handlingStrategy":"validation","validationCode":"// Validate a provider matching pattern before calling ParseMultiSourceMatchingPatterns.\nfunc validPatternSegmentCount(s string) error {\n    parts := strings.Split(s, \"/\")\n    if len(parts) < 2 || len(parts) > 3 {\n        return fmt.Errorf(\"pattern %q must have 2 or 3 slash-separated segments\", s)\n    }\n    for _, p := range parts {\n        if p == \"\" {\n            return fmt.Errorf(\"pattern %q has an empty segment\", s)\n        }\n    }\n    return nil\n}\n\n// usage:\n// for _, p := range includePatterns {\n//     if err := validPatternSegmentCount(p); err != nil { return err }\n// }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat patterns as host?/namespace/type and lint them in config-load tests.","Reject empty segments (leading/trailing/double slashes) before parsing.","Document the 2-or-3-segment rule wherever include/exclude is configured."],"tags":["provider-config","pattern","validation","multi-source"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}