{"record":{"id":"4daa0da3ba7fbf7f","repo":"caddyserver/caddy","slug":"parsing-upstream-url-v","errorCode":null,"errorMessage":"parsing upstream URL: %v","messagePattern":"parsing upstream URL: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/reverseproxy/addresses.go","lineNumber":84,"sourceCode":"\tvar network, scheme, host, port string\n\n\tif strings.Contains(upstreamAddr, \"://\") {\n\t\t// we get a parsing error if a placeholder is specified\n\t\t// so we return a more user-friendly error message instead\n\t\t// to explain what to do instead\n\t\tif strings.Contains(upstreamAddr, \"{\") {\n\t\t\treturn parsedAddr{}, fmt.Errorf(\"due to parsing difficulties, placeholders are not allowed when an upstream address contains a scheme\")\n\t\t}\n\n\t\ttoURL, err := url.Parse(upstreamAddr)\n\t\tif err != nil {\n\t\t\t// if the error seems to be due to a port range,\n\t\t\t// try to replace the port range with a dummy\n\t\t\t// single port so that url.Parse() will succeed\n\t\t\tif strings.Contains(err.Error(), \"invalid port\") && strings.Contains(err.Error(), \"-\") {\n\t\t\t\tindex := strings.LastIndex(upstreamAddr, \":\")\n\t\t\t\tif index == -1 {\n\t\t\t\t\treturn parsedAddr{}, fmt.Errorf(\"parsing upstream URL: %v\", err)\n\t\t\t\t}\n\t\t\t\tportRange := upstreamAddr[index+1:]\n\t\t\t\tif strings.Count(portRange, \"-\") != 1 {\n\t\t\t\t\treturn parsedAddr{}, fmt.Errorf(\"parsing upstream URL: parse \\\"%v\\\": port range invalid: %v\", upstreamAddr, portRange)\n\t\t\t\t}\n\t\t\t\ttoURL, err = url.Parse(strings.ReplaceAll(upstreamAddr, portRange, \"0\"))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn parsedAddr{}, fmt.Errorf(\"parsing upstream URL: %v\", err)\n\t\t\t\t}\n\t\t\t\tport = portRange\n\t\t\t} else {\n\t\t\t\treturn parsedAddr{}, fmt.Errorf(\"parsing upstream URL: %v\", err)\n\t\t\t}\n\t\t}\n\t\tif port == \"\" {\n\t\t\tport = toURL.Port()\n\t\t}\n","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/reverseproxy/addresses.go#L66-L102","documentation":"A scheme-bearing upstream address failed url.Parse, and the failure was not the port-range special case (or the address had no ':' at all before the suspected port range). The '%v' suffix carries Go's url.Parse error, usually 'invalid port' or a malformed URL.","triggerScenarios":"Calling parseUpstreamDialAddress with values like 'https://host:notaport', 'http://[bad', or an address whose error message contains 'invalid port' but has no last colon; also reached from 'caddy reverse-proxy --to' with such a value.","commonSituations":"Non-numeric or out-of-range ports, unescaped characters in the host, or a port range error where LastIndex(':') finds no colon.","solutions":["Check the wrapped url.Parse error text and fix the host/port portion of the upstream address.","Ensure the port is numeric and in 1-65535, and that port ranges contain exactly one dash (e.g. :8080-8090).","URL-encode or bracket IPv6 literals, e.g. 'http://[::1]:8080'."],"exampleFix":"# before\nreverse_proxy http://backend:notaport\n\n# after\nreverse_proxy http://backend:8080","handlingStrategy":"validation","validationCode":"// pre-check any scheme-bearing upstream with the same parser Go uses\nif _, err := url.Parse(addr); err != nil {\n    return fmt.Errorf(\"upstream %q is not a parseable URL: %v\", addr, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always quote upstream addresses in Caddyfiles to avoid shell/host mangling.","Use bracketed IPv6 literals: [::1]:8080.","Keep the form scheme://host:numeric-port."],"tags":["reverse-proxy","upstream","url-parsing","configuration"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}