hashicorp/terraform · error
invalid response content from mirror server: %s
Error message
invalid response content from mirror server: %s
What it means
After a 200 response to the versions index, the body is JSON-decoded into ListVersionsResponseBody ({"versions": {...}}). If decoding fails the request is failed with errQueryFailed wrapping this message. It means the mirror served a 200 with a body that is not valid JSON or does not match the protocol shape.
Source
Thrown at internal/getproviders/http_mirror_source.go:146
case http.StatusOK:
// Great!
case http.StatusNotFound:
return nil, nil, ErrProviderNotFound{
Provider: provider,
}
case http.StatusUnauthorized, http.StatusForbidden:
return nil, nil, s.errUnauthorized(finalURL)
default:
return nil, nil, s.errQueryFailed(provider, fmt.Errorf("server returned unsuccessful status %d", statusCode))
}
// If we got here then the response had status OK and so our body
// will be non-nil and should contain some JSON for us to parse.
var bodyContent ListVersionsResponseBody
dec := json.NewDecoder(body)
if err := dec.Decode(&bodyContent); err != nil {
return nil, nil, s.errQueryFailed(provider, fmt.Errorf("invalid response content from mirror server: %s", err))
}
if len(bodyContent.Versions) == 0 {
return nil, nil, nil
}
ret := make(VersionList, 0, len(bodyContent.Versions))
for versionStr := range bodyContent.Versions {
version, err := ParseVersion(versionStr)
if err != nil {
log.Printf("[WARN] Ignoring invalid %s version string %q in provider mirror response", provider, versionStr)
continue
}
ret = append(ret, version)
}
ret.Sort()
return ret, nil, nil
}View on GitHub (pinned to c9def3e214)
Solutions
- Fetch the URL directly with curl and validate the body is JSON with a top-level "versions" object.
- Fix the mirror generator/server to emit the documented ListVersionsResponseBody schema.
- Ensure no proxy rewrites the body or injects an error page on 200.
Example fix
# before: mirror served an HTML error page with 200
curl -i https://mirror/tf/registry.terraform.io/hashicorp/aws/index.json
# HTTP/1.1 200 <html>Not Found</html>
# after: serve real JSON
# HTTP/1.1 200 Content-Type: application/json
# {"versions":{"5.0.0":{},"5.1.0":{}}} Defensive patterns
Strategy: try-catch
Validate before calling
// Preflight: fetch index.json and confirm it decodes as the protocol shape.
var body struct{ Versions map[string]struct{} `json:"versions"` }
if err := json.Unmarshal(raw, &body); err != nil {
return fmt.Errorf("mirror index.json is not valid: %w", err)
} Try / catch
var qf getproviders.ErrQueryFailed
if errors.As(err, &qf) && strings.Contains(qf.Error(), "invalid response content") {
// mirror protocol bug: surface to the mirror operator, do not retry blindly
} Prevention
- Validate mirror JSON with a schema check during mirror generation.
- Never serve HTML error pages with status 200.
- Write mirror files atomically (temp + rename).
When it happens
Trigger: Mirror returns 200 but the body is HTML (an error page from a proxy), truncated JSON, a BOM/encoding issue, or a JSON object missing the "versions" key with extra junk that breaks the decoder. The decode error is appended verbatim.
Common situations: Reverse proxy serves a custom error page with status 200; mirror generated by a script that emitted invalid JSON; compression mismatch (gzip body advertised as identity).
Related errors
- provider mirror does not have archive index for previously-r
- provider mirror returned invalid URL %q: %s
- provider mirror returned invalid provider hash %q: %s
- response has invalid Content-Type: %s
- response has invalid Content-Type: must be application/json
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/a47d15f15e9a66d1.
Report an issue: GitHub.