caddyserver/caddy · error

invalid header flag: %v

Error message

invalid header flag: %v

What it means

Thrown by the `caddy reverse-proxy` CLI command when the `--header-up` flag value cannot be read as a string array by pflag. This is a flag-parsing failure, not a header-format failure: the command line argument itself was malformed for the flag library. Caddy aborts startup with ExitCodeFailedStartup.

Source

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

		} else {
			// expand a port range into multiple upstreams
			for i := parsedAddr.StartPort; i <= parsedAddr.EndPort; i++ {
				upstreamPool = append(upstreamPool, &Upstream{
					Dial: caddy.JoinNetworkAddress("", parsedAddr.Host, fmt.Sprint(i)),
				})
			}
		}
	}

	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,
			},
		}
	}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Check the exact spelling and casing of --header-up against `caddy reverse-proxy --help` output for your binary
  2. Quote each header argument fully in shell scripts: --header-up "Field: value"
  3. Verify you are not mixing --header-up with deprecated or renamed flags from an older Caddy version
  4. Print the command as executed (e.g. `set -x` in bash) to see what the shell actually passed

Example fix

# before
caddy reverse-proxy --to localhost:9000 --header-up Host:example.com X-Custom:1
# after
caddy reverse-proxy --to localhost:9000 --header-up "Host: example.com" --header-up "X-Custom: 1"
Defensive patterns

Strategy: validation

Validate before calling

# before invoking, assert the flag parses as a repeated string array
if ! grep -qE -- '--header-up[= ]+[^ ].*' <<< "$*"; then echo "bad --header-up"; exit 1; fi
# simplest: always pass quoted "Field: value" pairs and check exit code of caddy

Try / catch

cmd := exec.Command("caddy", "reverse-proxy", "--to", to)
if out, err := cmd.CombinedOutput(); err != nil {
	log.Printf("reverse-proxy failed: %v\n%s", err, out)
	os.Exit(1)
}

Prevention

When it happens

Trigger: Running `caddy reverse-proxy --header-up ...` with a flag value pflag cannot interpret as a StringArray (e.g. the flag was already consumed as a different type, or a custom flag set misregistered the option). The source calls `fs.GetStringArray("header-up")` and any error from it is wrapped here.

Common situations: Typos in the flag name, using `=` vs space forms inconsistently, scripting the command with unquoted shell expansions that collapse or drop values, or version drift between Caddy releases that changed flag registration.

Related errors


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