caddyserver/caddy · error

header-down %d: invalid format "%s" (expecting "Field: value

Error message

header-down %d: invalid format "%s" (expecting "Field: value")

What it means

Each `--header-down` value is validated as `"Field: value"` using `strings.Cut` on the first colon. Missing colon, empty field name, or empty value (after TrimSpace) aborts startup with the 0-based index and raw string in the message.

Source

Thrown at modules/caddyhttp/reverseproxy/command.go:217

		handler.Headers = &headers.Handler{
			Request: &headers.HeaderOps{
				Set: reqHdr,
			},
		}
	}

	// set up header_down
	headerDown, err := fs.GetStringArray("header-down")
	if err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid header flag: %v", err)
	}
	if len(headerDown) > 0 {
		respHdr := make(http.Header)
		for i, h := range headerDown {
			key, val, found := strings.Cut(h, ":")
			key, val = strings.TrimSpace(key), strings.TrimSpace(val)
			if !found || key == "" || val == "" {
				return caddy.ExitCodeFailedStartup, fmt.Errorf("header-down %d: invalid format \"%s\" (expecting \"Field: value\")", i, h)
			}
			respHdr.Set(key, val)
		}
		if handler.Headers == nil {
			handler.Headers = &headers.Handler{}
		}
		handler.Headers.Response = &headers.RespHeaderOps{
			HeaderOps: &headers.HeaderOps{
				Set: respHdr,
			},
		}
	}

	if changeHost {
		if handler.Headers == nil {
			handler.Headers = new(headers.Handler)
		}
		if handler.Headers.Request == nil {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Format the value as "Field: value" with both parts non-empty
  2. Verify environment variables used in the value are exported in the shell launching caddy
  3. Use the reported index to locate the exact offending argument

Example fix

# before
caddy reverse-proxy --to localhost:9000 --header-down "Cache-Control"
# after
caddy reverse-proxy --to localhost:9000 --header-down "Cache-Control: no-cache"
Defensive patterns

Strategy: validation

Validate before calling

for i, h := range headerDowns {
	key, val, found := strings.Cut(h, ":")
	if !found || strings.TrimSpace(key) == "" || strings.TrimSpace(val) == "" {
		return fmt.Errorf("header-down %d invalid: %q", i, h)
	}
}

Prevention

When it happens

Trigger: `--header-down "Set-Cookie"` (no colon), `--header-down "X-Y: "` (empty value), or `--header-down ":v"` (empty name).

Common situations: Attempting to just declare a response header without a value, or environment-driven values that are empty at launch time.

Related errors


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