hashicorp/terraform · error · ErrQueryFailed
registry response includes invalid protocol string
Error message
registry response includes invalid protocol string %q: %s
What it means
Returned as ErrQueryFailed when a provider version listed by the registry advertises a protocol version string that fails ParseVersion (semver-like parsing). The '%q' is the bad protocol string and '%s' is the parse error. The registry contract requires each version's 'protocols' array to contain valid semver strings (e.g. '5.0', '6.0'); any malformed entry aborts the closest-protocol search.
Solutions
- Inspect the registry's /v1/providers/<addr>/versions response and correct the 'protocols' array entries to valid semver.
- Ensure the registry emits bare versions like '5.0' / '6.0' without a 'v' prefix or range operators.
- If you control the registry, add server-side validation to reject malformed protocol strings before publication.
- Pin the provider version explicitly in required_providers to avoid triggering closest-protocol fallback on bad metadata.
Example fix
// before (registry JSON)
{"versions":[{"version":"1.0.0","protocols":["v5.0"]}]}
// after
{"versions":[{"version":"1.0.0","protocols":["5.0"]}]} Defensive patterns
Strategy: validation
Validate before calling
// Validate a 'protocols' array before publishing a registry response.
func validateProtocols(protos []string) error {
for _, p := range protos {
if _, err := getproviders.ParseVersion(p); err != nil {
return fmt.Errorf("invalid protocol %q: %w", p, err)
}
}
return nil
} Prevention
- Publish registry metadata through tooling that validates semver protocol strings.
- Pin required_providers versions to avoid closest-protocol fallback over bad metadata.
- Add CI schema tests for private registry responses.
When it happens
Trigger: c.ProviderVersions returns a map whose inner 'protocols' array contains a non-semver token such as 'v5', '5.x', 'latest', or an empty string, and that version is reached during the backwards precedence walk in findClosestProtocolCompatibleVersion.
Common situations: Custom or private registry emitting 'protocols': ['v5.0'] instead of ['5.0']; a registry returning a 'latest' sentinel; partial JSON where a field was misnamed and decodes to an empty string; version skew after a registry API change.
Related errors
- architecture portion must not contain whitespace
- can't use local directory
- failed to retrieve credentials for
- failed to retrieve cryptographic signature for provider
- must be two words separated by an underscore
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/aade986a227f3f3f.
Report an issue: GitHub.
Appendix: source
Thrown at internal/getproviders/registry_client.go:395
v, err := ParseVersion(versionStr)
if err != nil {
log.Printf("[WARN] registry response includes invalid version string %q. skipping: %s", versionStr, err)
continue
}
versionList = append(versionList, v)
}
versionList.Sort() // lowest precedence first, preserving order when equal precedence
protoVersions := MeetingConstraints(SupportedPluginProtocols)
FindMatch:
// put the versions in increasing order of precedence
for index := len(versionList) - 1; index >= 0; index-- { // walk backwards to consider newer versions first
for _, protoStr := range available[versionList[index].String()] {
p, err := ParseVersion(protoStr)
if err != nil {
return UnspecifiedVersion, ErrQueryFailed{
Provider: provider,
Wrapped: fmt.Errorf("registry response includes invalid protocol string %q: %s", protoStr, err),
}
}
if protoVersions.Has(p) {
match = versionList[index]
break FindMatch
}
}
}
return match, nil
}
func (c *registryClient) addHeadersToRequest(req *http.Request) {
if c.creds != nil {
c.creds.PrepareRequest(req)
}
req.Header.Set(terraformVersionHeader, version.String())
}
View on GitHub (pinned to d32a084675)