caddyserver/caddy · error

preparing request for upstream round-trip: %v

Error message

preparing request for upstream round-trip: %v

What it means

Error "preparing request for upstream round-trip: %v" thrown in caddyserver/caddy.

Source

Thrown at modules/caddyhttp/reverseproxy/reverseproxy.go:492

func (b *bodyNopCloserIfNotRead) Close() error {
	// don't close the body
	if b.read == 0 {
		return nil
	}
	// close as usual, when -1, any read will return EOF as the original read will do
	// in other cases, the read will fail as body is closed because we do not want partial bodies to be sent to the upstream
	// users can buffer the entire request body to allow the request to be resent
	return b.ReadCloser.Close()
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
	repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)

	// prepare the request for proxying; this is needed only once
	clonedReq, err := h.prepareRequest(r, repl)
	if err != nil {
		return caddyhttp.Error(http.StatusInternalServerError,
			fmt.Errorf("preparing request for upstream round-trip: %v", err))
	}

	// websocket over http2 or http3 if extended connect is enabled, assuming backend doesn't support this, the request will be modified to http1.1 upgrade
	// Both use the same upgrade mechanism: server advertizes extended connect support, and client sends the pseudo header :protocol in a CONNECT request
	// The quic-go http3 implementation also puts :protocol in r.Proto for CONNECT requests (quic-go/http3/headers.go@70-72,185,203)
	// TODO: once we can reliably detect backend support this, it can be removed for those backends
	if (r.ProtoMajor == 2 && r.Method == http.MethodConnect && r.Header.Get(":protocol") == "websocket") ||
		(r.ProtoMajor == 3 && r.Method == http.MethodConnect && r.Proto == "websocket") {
		clonedReq.Header.Del(":protocol")
		// keep the body for later use. http1.1 upgrade uses http.NoBody
		caddyhttp.SetVar(clonedReq.Context(), "extended_connect_websocket_body", clonedReq.Body)
		clonedReq.Body = http.NoBody
		clonedReq.Method = http.MethodGet
		clonedReq.Header.Set("Upgrade", "websocket")
		clonedReq.Header.Set("Connection", "Upgrade")
		key := make([]byte, 16)
		_, randErr := rand.Read(key)
		if randErr != nil {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Check the reverse proxy rewrite and header configuration; the wrapped error explains why the request could not be prepared.

When it happens

Trigger: Thrown at modules/caddyhttp/reverseproxy/reverseproxy.go:492 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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