{"record":{"id":"e97336d8b243dd29","repo":"caddyserver/caddy","slug":"cannot-define-both-exclude-and-include-lists-a","errorCode":null,"errorMessage":"cannot define both 'exclude' and 'include' lists at the same time","messagePattern":"cannot define both 'exclude' and 'include' lists at the same time","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/reverseproxy/copyresponse.go","lineNumber":115,"sourceCode":"\tExclude []string `json:\"exclude,omitempty\"`\n\n\tincludeMap map[string]struct{}\n\texcludeMap map[string]struct{}\n\tctx        caddy.Context\n}\n\n// CaddyModule returns the Caddy module information.\nfunc (CopyResponseHeadersHandler) CaddyModule() caddy.ModuleInfo {\n\treturn caddy.ModuleInfo{\n\t\tID:  \"http.handlers.copy_response_headers\",\n\t\tNew: func() caddy.Module { return new(CopyResponseHeadersHandler) },\n\t}\n}\n\n// Validate ensures the h's configuration is valid.\nfunc (h *CopyResponseHeadersHandler) Validate() error {\n\tif len(h.Exclude) > 0 && len(h.Include) > 0 {\n\t\treturn fmt.Errorf(\"cannot define both 'exclude' and 'include' lists at the same time\")\n\t}\n\n\treturn nil\n}\n\n// Provision ensures that h is set up properly before use.\nfunc (h *CopyResponseHeadersHandler) Provision(ctx caddy.Context) error {\n\th.ctx = ctx\n\n\t// Optimize the include list by converting it to a map\n\tif len(h.Include) > 0 {\n\t\th.includeMap = map[string]struct{}{}\n\t}\n\tfor _, field := range h.Include {\n\t\th.includeMap[http.CanonicalHeaderKey(field)] = struct{}{}\n\t}\n\n\t// Optimize the exclude list by converting it to a map","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/reverseproxy/copyresponse.go#L97-L133","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Keep exactly one of include or exclude and delete the other","If you need 'all except a few', use exclude only and remove the include list","If you need 'only these', use include only"],"exampleFix":"# before\nhandle_response {\n\tcopy_response_headers {\n\t\tinclude Content-Type\n\t\texclude Set-Cookie\n\t}\n}\n# after\nhandle_response {\n\tcopy_response_headers {\n\t\tinclude Content-Type\n\t}\n}","handlingStrategy":"validation","validationCode":"if len(include) > 0 && len(exclude) > 0 {\n\treturn fmt.Errorf(\"pick one: include (%d) or exclude (%d)\", len(include), len(exclude))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat include/exclude as mutually exclusive at the schema level in config templates","When adding one, grep the config block for the other and delete it"],"tags":["reverse-proxy","caddyfile","validation","handle-response"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}