caddyserver/caddy · error

invalid header flag: %v

Error message

invalid header flag: %v

What it means

'caddy respond' reads repeated --header flags via fl.GetStringArray; this error wraps a failure of that flag lookup. It almost never fires from normal use — it indicates the flag was not registered/typed as a string slice in the running command context (e.g. a mismatched custom flag setup or embedded CLI misuse).

Source

Thrown at modules/caddyhttp/staticresp.go:373

	// if we still need a body, see if stdin is being piped
	if body == "" {
		stdinInfo, err := os.Stdin.Stat()
		if err != nil {
			return caddy.ExitCodeFailedStartup, err
		}
		if stdinInfo.Mode()&os.ModeNamedPipe != 0 {
			bodyBytes, err := io.ReadAll(os.Stdin)
			if err != nil {
				return caddy.ExitCodeFailedStartup, err
			}
			body = string(bodyBytes)
		}
	}

	// build headers map
	headers, err := fl.GetStringArray("header")
	if err != nil {
		return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid header flag: %v", err)
	}
	hdr := make(http.Header)
	for i, h := range headers {
		key, val, found := strings.Cut(h, ":")
		key, val = strings.TrimSpace(key), strings.TrimSpace(val)
		if !found || key == "" || val == "" {
			return caddy.ExitCodeFailedStartup, fmt.Errorf("header %d: invalid format \"%s\" (expecting \"Field: value\")", i, h)
		}
		hdr.Set(key, val)
	}

	// build each HTTP server
	httpApp := App{Servers: make(map[string]*Server)}

	// expand listen address, if more than one port
	listenAddr, err := caddy.ParseNetworkAddress(listen)
	if err != nil {
		return caddy.ExitCodeFailedStartup, err

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Use the stock 'caddy respond' command rather than a custom flag harness
  2. If embedding, register the header flag with the same name and string-slice type before calling cmdRespond
  3. Reinstall a consistent Caddy build to rule out mixed binaries

Example fix

// before (custom harness)
fl := caddycmd.Flags{} // no header flag registered
_, err := cmdRespond(fl)

// after
fl.RegisterStringArray("header", "", "" /* ... */) // ensure 'header' is a []string flag
Defensive patterns

Strategy: validation

Validate before calling

// when embedding the CLI, register the flag before invoking cmdRespond:
fl := caddycmd.Flags{}
fl.String("header", "") // must match the type cmdRespond reads via GetStringArray
if _, err := fl.GetStringArray("header"); err != nil {
    return fmt.Errorf("header flag misconfigured: %w", err)
}

Prevention

When it happens

Trigger: Invoking cmdRespond through a custom caddycmd.Flags that did not define "header" as a string-array flag; binary/version mismatch between the CLI wrapper and command implementation.

Common situations: Embedding Caddy's CLI in another tool with a hand-built flag set; downgrading/mixing builds where the header flag registration changed.

Related errors


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