{"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/c9def3e214014c1188faabfc4a5bde5095139765/internal/getproviders/http_mirror_source.go#L119-L155","documentation":"Inside AvailableVersions, after handling 200/404/401/403 explicitly, any other status code from the mirror's index.json request is reported via errQueryFailed with this message. It covers server-side failures (5xx) and unexpected 2xx/3xx that slipped through. Returned wrapped as ErrQueryFailed.","triggerScenarios":"GET <host>/<ns>/<type>/index.json returns 500, 502, 503, 504, 429, or another non-handled status. Happens when the mirror is overloaded, a gateway errors, or an auth-adjacent filter returns 401-like behavior as a different code.","commonSituations":"Mirror behind a flaky gateway; rate limiting (429) from a shared mirror; transient backend outage during terraform init.","solutions":["Retry the operation after a short backoff — 5xx/429 are often transient.","Check the mirror service health and logs for the failing path.","If 429, raise rate limits or stagger concurrent terraform runs against the mirror."],"exampleFix":"// before\nvers, _, err := mirror.AvailableVersions(ctx, p)\nif err != nil { return err } // surfaces \"server returned unsuccessful status 503\"\n\n// after\nvers, _, err := retryOn5xx(ctx, func() (getproviders.VersionList, getproviders.Warnings, error) {\n    return mirror.AvailableVersions(ctx, p)\n})","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var qf getproviders.ErrQueryFailed\nif errors.As(err, &qf) {\n    // qf.Wrapped holds the inner \"server returned unsuccessful status N\" error;\n    // retry with exponential backoff for transient (5xx/429) statuses\n}","preventionTips":["Wrap AvailableVersions in a bounded retry with backoff for transient statuses.","Monitor mirror error rates and alert on 5xx spikes.","Stagger concurrent terraform init runs against a shared mirror."],"tags":["network","http","mirror","server-error"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}