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

  1. Read the message and id — the API states the exact reason (e.g. unknown package, build error)
  2. Verify the module path: check the plugin's README or 'go list -m' against what you passed to 'caddy add-package'
  3. Pin a known-good version: caddy add-package github.com/authelia/authelia@v4.38.0
  4. 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

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


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/9db6f0bd5aa8a3c9. Report an issue: GitHub.