{"record":{"id":"47bd12f45b118ede","repo":"hashicorp/packer","slug":"s-returned-status-d","errorCode":null,"errorMessage":"%s returned status %d","messagePattern":"(.+?) returned status (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packer/plugin-getter/remote/getter.go","lineNumber":130,"sourceCode":"\t\treturn nil, err\n\t}\n\treturn io.NopCloser(buf), nil\n}\n\n// fetchStream returns the response body of url for the caller to consume\n// and close; fetch buffers it, for the small metadata files.\nfunc (g *Getter) fetchStream(url string) (io.ReadCloser, error) {\n\tif g.HttpClient == nil {\n\t\tg.HttpClient = &http.Client{}\n\t}\n\tlog.Printf(\"[DEBUG] remote-getter: getting %q\", url)\n\tresp, err := g.HttpClient.Get(url)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to fetch %s: %w\", url, err)\n\t}\n\tif resp.StatusCode >= 400 {\n\t\t_ = resp.Body.Close()\n\t\treturn nil, fmt.Errorf(\"%s returned status %d\", url, resp.StatusCode)\n\t}\n\treturn resp.Body, nil\n}\n\nfunc (g *Getter) fetch(url string) ([]byte, error) {\n\tbody, err := g.fetchStream(url)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() { _ = body.Close() }()\n\treturn io.ReadAll(body)\n}\n\n// pluginPath returns the URL path of the plugin below the host, e.g.\n// \"mirror/hashicorp/packer-plugin-docker\" for source\n// \"plugins.example.com/mirror/hashicorp/docker\".\nfunc pluginPath(opts plugingetter.GetOptions) (dir string, pluginType string) {\n\tparts := opts.PluginRequirement.Identifier.Parts()","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/packer/plugin-getter/remote/getter.go#L112-L148","documentation":"fetchStream treats any HTTP status >= 400 from the registry host as a failure and returns \"%s returned status %d\" after closing the body. Unlike 337 this is a successful HTTP round trip whose response is an error (404, 403, 500, etc.).","triggerScenarios":"The index.json / releases / meta URL answers with 4xx/5xx — e.g. a 404 because the plugin or version directory does not exist, 403 from a blocked/rate-limited client, or 500 from the registry.","commonSituations":"Typo'd plugin address (github.com/org/name) resolving to a nonexistent registry path; requesting a version that was deleted or never published; hitting GitHub/registry rate limits (403/429); custom mirror misconfigured path layout.","solutions":["Read the status code: 404 → verify the plugin address and version exist on the registry; 403/429 → wait or check rate limiting/auth; 5xx → retry later.","Correct the required_plugins source address if it points at a nonexistent org/repo.","Curl the failing URL directly to inspect the response body for more detail.","Re-run the install after the server-side issue resolves."],"exampleFix":"// before\nmyplugin = {\n  source = \"github.com/acme/packer-plugin-myplugin\"\n  version = \"= 9.9.9\"\n}\n// after (use a published version)\nmyplugin = {\n  source = \"github.com/acme/packer-plugin-myplugin\"\n  version = \"= 1.0.0\"\n}","handlingStrategy":"fallback","validationCode":"resp, err := http.Head(indexURL)\nif err == nil && resp.StatusCode >= 400 {\n    return fmt.Errorf(\"registry returned %d for %s; check address/version\", resp.StatusCode, indexURL)\n}","typeGuard":null,"tryCatchPattern":"if _, err := g.Get(\"releases\", opts); err != nil {\n    var statusErrPresent = strings.Contains(err.Error(), \"returned status\")\n    if statusErrPresent && strings.Contains(err.Error(), \"404\") {\n        // verify plugin address/version exist; do not blind-retry\n    } else if statusErrPresent {\n        // 5xx/429: wait and retry with backoff\n    }\n}","preventionTips":["Validate plugin source addresses and pinned versions against the registry before install.","Handle rate limits by authenticating or throttling bulk installs.","Curl the exact URL from the error to read the server's response body."],"tags":["packer","plugin-getter","http-status","registry"],"backgroundTag":"http-4xx-5xx-response","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}