caddyserver/caddy · error
header-up %d: invalid format "%s" (expecting "Field: value")
Error message
header-up %d: invalid format "%s" (expecting "Field: value")
What it means
The `caddy reverse-proxy` command validates each `--header-up` value as `"Field: value"`. The string is split on the first colon with `strings.Cut`; if no colon is found, or either side is empty after trimming whitespace, Caddy exits with this error naming the offending index and raw string.
Source
Thrown at modules/caddyhttp/reverseproxy/command.go:195
}
handler := Handler{
TransportRaw: caddyconfig.JSONModuleObject(ht, "protocol", "http", nil),
Upstreams: upstreamPool,
}
// set up header_up
headerUp, err := fs.GetStringArray("header-up")
if err != nil {
return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid header flag: %v", err)
}
if len(headerUp) > 0 {
reqHdr := make(http.Header)
for i, h := range headerUp {
key, val, found := strings.Cut(h, ":")
key, val = strings.TrimSpace(key), strings.TrimSpace(val)
if !found || key == "" || val == "" {
return caddy.ExitCodeFailedStartup, fmt.Errorf("header-up %d: invalid format \"%s\" (expecting \"Field: value\")", i, h)
}
reqHdr.Set(key, val)
}
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 {View on GitHub (pinned to 50e54ee279)
Solutions
- Rewrite the flag value as "Field: value" with both sides non-empty
- If the value comes from an environment variable, verify it is set before launching the command
- Check the index reported in the message (0-based) against the Nth --header-up argument to find the bad one
Example fix
# before caddy reverse-proxy --to localhost:9000 --header-up "X-Forwarded-Proto" # after caddy reverse-proxy --to localhost:9000 --header-up "X-Forwarded-Proto: https"
Defensive patterns
Strategy: validation
Validate before calling
func validHeaderFlag(s string) bool {
key, val, found := strings.Cut(s, ":")
return found && strings.TrimSpace(key) != "" && strings.TrimSpace(val) != ""
}
for i, h := range headerUps {
if !validHeaderFlag(h) {
log.Fatalf("header-up %d invalid: %q", i, h)
}
} Prevention
- Adopt the "Field: value" shape as a convention in scripts
- Fail fast in CI on empty env vars used inside header flags: test -n "$KEY"
When it happens
Trigger: Passing `--header-up "X-Foo"` (no colon), `--header-up ": value"` (empty field name), `--header-up "X-Foo: "` (empty value), or `--header-up "X-Foo:"` (empty value after trim).
Common situations: Forgetting the colon separator, adding a trailing colon with no value, or a shell variable that expands to an empty string, e.g. `--header-up "X-Api-Key: $KEY"` when $KEY is unset in the environment.
Related errors
- header-down %d: invalid format "%s" (expecting "Field: value
- invalid header flag: %v
- loading initial config: %v
- invalid to flag: %v
- --to is required
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/62b9133e69edc785.
Report an issue: GitHub.