caddyserver/caddy · error

cannot define both 'exclude' and 'include' lists at the same

Error message

cannot define both 'exclude' and 'include' lists at the same time

What it means

`copy_response_headers` accepts either an `include` or an `exclude` list of header names, but not both — they are mutually exclusive semantics (copy only these vs copy all but these). Validate() rejects the config at load time when both are non-empty.

Source

Thrown at modules/caddyhttp/reverseproxy/copyresponse.go:115

	Exclude []string `json:"exclude,omitempty"`

	includeMap map[string]struct{}
	excludeMap map[string]struct{}
	ctx        caddy.Context
}

// CaddyModule returns the Caddy module information.
func (CopyResponseHeadersHandler) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:  "http.handlers.copy_response_headers",
		New: func() caddy.Module { return new(CopyResponseHeadersHandler) },
	}
}

// Validate ensures the h's configuration is valid.
func (h *CopyResponseHeadersHandler) Validate() error {
	if len(h.Exclude) > 0 && len(h.Include) > 0 {
		return fmt.Errorf("cannot define both 'exclude' and 'include' lists at the same time")
	}

	return nil
}

// Provision ensures that h is set up properly before use.
func (h *CopyResponseHeadersHandler) Provision(ctx caddy.Context) error {
	h.ctx = ctx

	// Optimize the include list by converting it to a map
	if len(h.Include) > 0 {
		h.includeMap = map[string]struct{}{}
	}
	for _, field := range h.Include {
		h.includeMap[http.CanonicalHeaderKey(field)] = struct{}{}
	}

	// Optimize the exclude list by converting it to a map

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Keep exactly one of include or exclude and delete the other
  2. If you need 'all except a few', use exclude only and remove the include list
  3. If you need 'only these', use include only

Example fix

# before
handle_response {
	copy_response_headers {
		include Content-Type
		exclude Set-Cookie
	}
}
# after
handle_response {
	copy_response_headers {
		include Content-Type
	}
}
Defensive patterns

Strategy: validation

Validate before calling

if len(include) > 0 && len(exclude) > 0 {
	return fmt.Errorf("pick one: include (%d) or exclude (%d)", len(include), len(exclude))
}

Prevention

When it happens

Trigger: Supplying both `include` and `exclude` subdirectives to copy_response_headers in the same handle_response block, or in JSON both the Include and Exclude arrays.

Common situations: Iteratively building config: a developer adds include, then later adds exclude to trim one more header instead of editing the include list, ending with both present.

Related errors


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