caddyserver/caddy · error

parsing upstream '%s': %w

Error message

parsing upstream '%s': %w

What it means

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).

Source

Thrown at modules/caddyhttp/reverseproxy/caddyfile.go:218

				Dial: pa.dialAddr(),
			})
		} else {
			// expand a port range into multiple upstreams
			for i := parsedAddr.StartPort; i <= parsedAddr.EndPort; i++ {
				h.Upstreams = append(h.Upstreams, &Upstream{
					Dial: caddy.JoinNetworkAddress("", parsedAddr.Host, fmt.Sprint(i)),
				})
			}
		}

		return nil
	}

	d.Next() // consume the directive name
	for _, up := range d.RemainingArgs() {
		err := appendUpstream(up)
		if err != nil {
			return fmt.Errorf("parsing upstream '%s': %w", up, err)
		}
	}

	for d.NextBlock(0) {
		// if the subdirective has an "@" prefix then we
		// parse it as a response matcher for use with "handle_response"
		if strings.HasPrefix(d.Val(), matcherPrefix) {
			err := caddyhttp.ParseNamedResponseMatcher(d.NewFromNextSegment(), h.responseMatchers)
			if err != nil {
				return err
			}
			continue
		}

		switch d.Val() {
		case "to":
			args := d.RemainingArgs()
			if len(args) == 0 {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Locate the failing upstream named in the message ('parsing upstream 'X'') and fix it using the underlying error text.
  2. Apply the same fixes as for parseUpstreamDialAddress errors: no placeholders with schemes, no paths/queries, consistent scheme/port.
  3. Run 'caddy validate --config' after each upstream edit to isolate the bad entry quickly.

Example fix

# before
reverse_proxy https://backend/api http://other:8080

# after
reverse_proxy https://backend http://other:8080
Defensive patterns

Strategy: validation

Validate before calling

// validate inline upstreams with the same rules before adapting config
for _, up := range strings.Fields(upstreamLine) {
    if strings.Contains(up, "://") {
        if u, err := url.Parse(up); err != nil || u.Path != "" || u.RawQuery != "" || u.Fragment != "" {
            return fmt.Errorf("inline upstream %q rejected", up)
        }
    }
}

Prevention

When it happens

Trigger: 'reverse_proxy upstream1 upstream2 ...' where one inline upstream is malformed, e.g. 'reverse_proxy https://{env.H} http://bad:!port'.

Common situations: Long upstream lists where one entry has a typo; converting from JSON to Caddyfile and carrying over full URLs with paths.

Related errors


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