{"record":{"id":"16bb209b21fe0c52","repo":"caddyserver/caddy","slug":"parsing-upstream-s-w","errorCode":null,"errorMessage":"parsing upstream '%s': %w","messagePattern":"parsing upstream '(.+?)': %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/reverseproxy/caddyfile.go","lineNumber":218,"sourceCode":"\t\t\t\tDial: pa.dialAddr(),\n\t\t\t})\n\t\t} else {\n\t\t\t// expand a port range into multiple upstreams\n\t\t\tfor i := parsedAddr.StartPort; i <= parsedAddr.EndPort; i++ {\n\t\t\t\th.Upstreams = append(h.Upstreams, &Upstream{\n\t\t\t\t\tDial: caddy.JoinNetworkAddress(\"\", parsedAddr.Host, fmt.Sprint(i)),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\treturn nil\n\t}\n\n\td.Next() // consume the directive name\n\tfor _, up := range d.RemainingArgs() {\n\t\terr := appendUpstream(up)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"parsing upstream '%s': %w\", up, err)\n\t\t}\n\t}\n\n\tfor d.NextBlock(0) {\n\t\t// if the subdirective has an \"@\" prefix then we\n\t\t// parse it as a response matcher for use with \"handle_response\"\n\t\tif strings.HasPrefix(d.Val(), matcherPrefix) {\n\t\t\terr := caddyhttp.ParseNamedResponseMatcher(d.NewFromNextSegment(), h.responseMatchers)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch d.Val() {\n\t\tcase \"to\":\n\t\t\targs := d.RemainingArgs()\n\t\t\tif len(args) == 0 {","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/reverseproxy/caddyfile.go#L200-L236","documentation":"While parsing the reverse_proxy directive's inline arguments (the upstream list on the directive line itself), appendUpstream failed for one address. The '%w' suffix is the underlying error, typically one of the parseUpstreamDialAddress failures (placeholders with scheme, bad port, path in URL, scheme/port conflict).","triggerScenarios":"'reverse_proxy upstream1 upstream2 ...' where one inline upstream is malformed, e.g. 'reverse_proxy https://{env.H} http://bad:!port'.","commonSituations":"Long upstream lists where one entry has a typo; converting from JSON to Caddyfile and carrying over full URLs with paths.","solutions":["Locate the failing upstream named in the message ('parsing upstream 'X'') and fix it using the underlying error text.","Apply the same fixes as for parseUpstreamDialAddress errors: no placeholders with schemes, no paths/queries, consistent scheme/port.","Run 'caddy validate --config' after each upstream edit to isolate the bad entry quickly."],"exampleFix":"# before\nreverse_proxy https://backend/api http://other:8080\n\n# after\nreverse_proxy https://backend http://other:8080","handlingStrategy":"validation","validationCode":"// validate inline upstreams with the same rules before adapting config\nfor _, up := range strings.Fields(upstreamLine) {\n    if strings.Contains(up, \"://\") {\n        if u, err := url.Parse(up); err != nil || u.Path != \"\" || u.RawQuery != \"\" || u.Fragment != \"\" {\n            return fmt.Errorf(\"inline upstream %q rejected\", up)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint each upstream in long lists individually to localize failures.","Run 'caddy adapt' + 'caddy validate' in CI for every config change.","Keep upstream addresses minimal: host or scheme://host[:port]."],"tags":["reverse-proxy","caddyfile","upstream","configuration"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}