{"record":{"id":"2fa820308328287a","repo":"hashicorp/terraform","slug":"server-returned-unsuccessful-status-d","errorCode":null,"errorMessage":"server returned unsuccessful status %d","messagePattern":"server returned unsuccessful status (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getproviders/http_mirror_source.go","lineNumber":137,"sourceCode":"\t\tif body != nil {\n\t\t\tbody.Close()\n\t\t}\n\t}()\n\tif err != nil {\n\t\treturn nil, nil, s.errQueryFailed(provider, err)\n\t}\n\n\tswitch statusCode {\n\tcase http.StatusOK:\n\t\t// Great!\n\tcase http.StatusNotFound:\n\t\treturn nil, nil, ErrProviderNotFound{\n\t\t\tProvider: provider,\n\t\t}\n\tcase http.StatusUnauthorized, http.StatusForbidden:\n\t\treturn nil, nil, s.errUnauthorized(finalURL)\n\tdefault:\n\t\treturn nil, nil, s.errQueryFailed(provider, fmt.Errorf(\"server returned unsuccessful status %d\", statusCode))\n\t}\n\n\t// If we got here then the response had status OK and so our body\n\t// will be non-nil and should contain some JSON for us to parse.\n\tvar bodyContent ListVersionsResponseBody\n\n\tdec := json.NewDecoder(body)\n\tif err := dec.Decode(&bodyContent); err != nil {\n\t\treturn nil, nil, s.errQueryFailed(provider, fmt.Errorf(\"invalid response content from mirror server: %s\", err))\n\t}\n\n\tif len(bodyContent.Versions) == 0 {\n\t\treturn nil, nil, nil\n\t}\n\tret := make(VersionList, 0, len(bodyContent.Versions))\n\tfor versionStr := range bodyContent.Versions {\n\t\tversion, err := ParseVersion(versionStr)\n\t\tif err != nil {","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/getproviders/http_mirror_source.go#L119-L155","documentation":"In `AvailableVersions`, after handling 200, 404, 401/403, any other HTTP status falls through to the `default` arm and is wrapped as `ErrQueryFailed` with the numeric status. It represents an unexpected response from the network mirror's version index endpoint.","triggerScenarios":"`AvailableVersions` issues GET to the mirror's `<provider>/index.json`; `statusCode` is not in {200,404,401,403}; default at http_mirror_source.go:137.","commonSituations":"Mirror returns 5xx (server error, gateway timeout); 418/451 or other unusual status codes; rate limiting (429) from a CDN-fronted mirror; broken backend behind the mirror URL.","solutions":["Reproduce with `curl -i https://<mirror>/<provider>/index.json` to see the raw status and body.","If 429/5xx, retry after a delay; check mirror health and capacity.","Confirm the mirror URL and provider path are correct; fix the mirror backend.","If the mirror is permanently broken, remove its `network_mirror` block and fall back to the default registry."],"exampleFix":"// before: 502 from mirror\nterraform init // server returned unsuccessful status 502\n// after: hit the endpoint directly, fix upstream, or drop the mirror\n$ curl -i https://mirror.local/hashicorp/aws/index.json\n# once 200, re-run init","handlingStrategy":"retry","validationCode":"// Pre-flight the version index endpoint\nresp, err := http.Get(indexURL)\nif err != nil { return err }\ndefer resp.Body.Close()\nif resp.StatusCode != 200 {\n    return fmt.Errorf(\"mirror index not ready: %d\", resp.StatusCode)\n}","typeGuard":null,"tryCatchPattern":"// Retry on 5xx/429\nerr := retryDo(ctx, 3, backoff, func() error {\n    _, e := src.AvailableVersions(ctx, provider)\n    return e\n})","preventionTips":["Health-check the mirror before relying on it.","Configure retries for transient HTTP statuses.","Fall back to the default registry when the mirror is unhealthy.","Document mirror SLA expectations for users."],"tags":["network","mirror","http-status","registry"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}