caddyserver/caddy · error
download failed: HTTP %d: %s (id=%s)
Error message
download failed: HTTP %d: %s (id=%s)
What it means
The download API returned HTTP >= 400 with a well-formed JSON error body, and this is that server-reported message surfaced verbatim (with the API's error ID). Common server-side rejections: unknown or unavailable plugin package, build failure for the requested combination, or invalid parameters (os/arch/packages).
Source
Thrown at cmd/packagesfuncs.go:302
zap.String("arch", qs.Get("arch")),
zap.Strings("packages", qs["p"]))
resp, err := http.Get(fmt.Sprintf("%s?%s", downloadPath, qs.Encode()))
if err != nil {
return nil, fmt.Errorf("secure request failed: %v", err)
}
if resp.StatusCode >= 400 {
var details struct {
StatusCode int `json:"status_code"`
Error struct {
Message string `json:"message"`
ID string `json:"id"`
} `json:"error"`
}
err2 := json.NewDecoder(resp.Body).Decode(&details)
if err2 != nil {
return nil, fmt.Errorf("download and error decoding failed: HTTP %d: %v", resp.StatusCode, err2)
}
return nil, fmt.Errorf("download failed: HTTP %d: %s (id=%s)", resp.StatusCode, details.Error.Message, details.Error.ID)
}
return resp, nil
}
func getPluginPackages(modules []moduleInfo) (map[string]pluginPackage, error) {
pluginPkgs := make(map[string]pluginPackage)
for _, mod := range modules {
if mod.goModule.Replace != nil {
return nil, fmt.Errorf("cannot auto-upgrade when Go module has been replaced: %s => %s",
mod.goModule.Path, mod.goModule.Replace.Path)
}
pluginPkgs[mod.goModule.Path] = pluginPackage{Version: mod.goModule.Version, Path: mod.goModule.Path}
}
return pluginPkgs, nil
}
func writeCaddyBinary(path string, body *io.ReadCloser, fileInfo os.FileInfo) error {
l := caddy.Log()View on GitHub (pinned to 50e54ee279)
Solutions
- Read the message and id — the API states the exact reason (e.g. unknown package, build error)
- Verify the module path: check the plugin's README or 'go list -m' against what you passed to 'caddy add-package'
- Pin a known-good version: caddy add-package github.com/authelia/authelia@v4.38.0
- If the build fails for the latest version, try the plugin's previous tagged version or build locally with xcaddy
Example fix
# before caddy add-package github.com/example/caddy-frobnicate # error: download failed: HTTP 400: unknown package (id=...) # after # correct module path from the plugin's README caddy add-package github.com/example/caddy-frob
Defensive patterns
Strategy: validation
Validate before calling
# confirm the module exists and builds before adding it go list -m -versions github.com/mholt/caddy-ratelimit 2>/dev/null || echo 'module not found'
Prevention
- Copy plugin module paths verbatim from their README/Go import path
- Pin explicit versions: caddy add-package <module>@<tag>
- Check plugin compatibility with your Caddy version before adding
When it happens
Trigger: Passing a plugin path that does not exist or is not a Caddy plugin to 'caddy add-package'; requesting a package version incompatible with the current Caddy core; the build API failing to compile the requested plugin set; platform not supported by a plugin.
Common situations: Typo in a module path (caddy-nginx instead of caddy-certmagic, etc.); plugin abandoned/renamed upstream; plugin not updated for the current Caddy version so the API's build fails.
Related errors
- download and error decoding failed: HTTP %d: %v
- unable to enumerate installed plugins: %v
- cannot auto-upgrade when Go module has been replaced: %s =>
- provisioning admin router module %s: %v
- stopping admin server: %ds timeout
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/9db6f0bd5aa8a3c9.
Report an issue: GitHub.