hashicorp/terraform · error
invalid provider matching pattern
Error message
invalid provider matching pattern %q: must have either two or three slash-separated segments
What it means
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.
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.
Example fix
// before include = ["aws"] exclude = ["registry.terraform.io/hashicorp/aws/zip"] // after include = ["hashicorp/aws"] exclude = ["registry.terraform.io/hashicorp/aws"]
Defensive patterns
Strategy: validation
Validate before calling
// Validate a provider matching pattern before calling ParseMultiSourceMatchingPatterns.
func validPatternSegmentCount(s string) error {
parts := strings.Split(s, "/")
if len(parts) < 2 || len(parts) > 3 {
return fmt.Errorf("pattern %q must have 2 or 3 slash-separated segments", s)
}
for _, p := range parts {
if p == "" {
return fmt.Errorf("pattern %q has an empty segment", s)
}
}
return nil
}
// usage:
// for _, p := range includePatterns {
// if err := validPatternSegmentCount(p); err != nil { return err }
// } Prevention
- 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.
When it happens
Trigger: 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, "/").
Common situations: 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.
Related errors
- invalid provider matching pattern
- invalid provider matching pattern
- invalid provider type
- invalid registry namespace
- invalid hostname in provider matching pattern
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/0b905f369fb84212.
Report an issue: GitHub.
Appendix: source
Thrown at internal/getproviders/multi_source.go:151
// The Provider address values in a MultiSourceMatchingPatterns are special in
// that any of Hostname, Namespace, or Type can be getproviders.Wildcard
// to indicate that any concrete value is permitted for that segment.
type MultiSourceMatchingPatterns []addrs.Provider
// ParseMultiSourceMatchingPatterns parses a slice of strings containing the
// string form of provider matching patterns and, if all the given strings are
// valid, returns the corresponding, normalized, MultiSourceMatchingPatterns
// value.
func ParseMultiSourceMatchingPatterns(strs []string) (MultiSourceMatchingPatterns, error) {
if len(strs) == 0 {
return nil, nil
}
ret := make(MultiSourceMatchingPatterns, len(strs))
for i, str := range strs {
parts := strings.Split(str, "/")
if len(parts) < 2 || len(parts) > 3 {
return nil, fmt.Errorf("invalid provider matching pattern %q: must have either two or three slash-separated segments", str)
}
host := defaultRegistryHost
explicitHost := len(parts) == 3
if explicitHost {
givenHost := parts[0]
if givenHost == "*" {
host = svchost.Hostname(Wildcard)
} else {
normalHost, err := svchost.ForComparison(givenHost)
if err != nil {
return nil, fmt.Errorf("invalid hostname in provider matching pattern %q: %s", str, err)
}
// The remaining code below deals only with the namespace/type portions.
host = normalHost
}
parts = parts[1:]View on GitHub (pinned to d32a084675)