caddyserver/caddy · error
parsing upstream URL: %v
Error message
parsing upstream URL: %v
What it means
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.
Source
Thrown at modules/caddyhttp/reverseproxy/addresses.go:84
var network, scheme, host, port string
if strings.Contains(upstreamAddr, "://") {
// we get a parsing error if a placeholder is specified
// so we return a more user-friendly error message instead
// to explain what to do instead
if strings.Contains(upstreamAddr, "{") {
return parsedAddr{}, fmt.Errorf("due to parsing difficulties, placeholders are not allowed when an upstream address contains a scheme")
}
toURL, err := url.Parse(upstreamAddr)
if err != nil {
// if the error seems to be due to a port range,
// try to replace the port range with a dummy
// single port so that url.Parse() will succeed
if strings.Contains(err.Error(), "invalid port") && strings.Contains(err.Error(), "-") {
index := strings.LastIndex(upstreamAddr, ":")
if index == -1 {
return parsedAddr{}, fmt.Errorf("parsing upstream URL: %v", err)
}
portRange := upstreamAddr[index+1:]
if strings.Count(portRange, "-") != 1 {
return parsedAddr{}, fmt.Errorf("parsing upstream URL: parse \"%v\": port range invalid: %v", upstreamAddr, portRange)
}
toURL, err = url.Parse(strings.ReplaceAll(upstreamAddr, portRange, "0"))
if err != nil {
return parsedAddr{}, fmt.Errorf("parsing upstream URL: %v", err)
}
port = portRange
} else {
return parsedAddr{}, fmt.Errorf("parsing upstream URL: %v", err)
}
}
if port == "" {
port = toURL.Port()
}
View on GitHub (pinned to 50e54ee279)
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'.
Example fix
# before reverse_proxy http://backend:notaport # after reverse_proxy http://backend:8080
Defensive patterns
Strategy: validation
Validate before calling
// pre-check any scheme-bearing upstream with the same parser Go uses
if _, err := url.Parse(addr); err != nil {
return fmt.Errorf("upstream %q is not a parseable URL: %v", addr, err)
} Prevention
- Always quote upstream addresses in Caddyfiles to avoid shell/host mangling.
- Use bracketed IPv6 literals: [::1]:8080.
- Keep the form scheme://host:numeric-port.
When it happens
Trigger: 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.
Common situations: Non-numeric or out-of-range ports, unescaped characters in the host, or a port range error where LastIndex(':') finds no colon.
Related errors
- due to parsing difficulties, placeholders are not allowed wh
- parsing upstream URL: parse "%v": port range invalid: %v
- for now, URLs for proxy upstreams only support scheme, host,
- parsing upstream '%s': %w
- upstream address has conflicting scheme (http://) and port (
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/4daa0da3ba7fbf7f.
Report an issue: GitHub.