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

  1. Inspect the registry's /v1/providers/<addr>/versions response and correct the 'protocols' array entries to valid semver.
  2. Ensure the registry emits bare versions like '5.0' / '6.0' without a 'v' prefix or range operators.
  3. If you control the registry, add server-side validation to reject malformed protocol strings before publication.
  4. 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

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


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)