cloudflare/cloudflared · error

Error writing response header

Error message

Error writing response header

What it means

After a successful origin response, proxyHTTPRequest writes the status code and origin headers back to the edge via w.WriteRespHeaders. If that write fails, it is wrapped as 'Error writing response header'. This indicates the downstream connection to Cloudflare's edge (or the client) broke while relaying the response headers, not an origin problem.

Source

Thrown at proxy/proxy.go:243

		}
		return errors.Wrap(err, "Unable to reach the origin service. The service may be down or it may not be responding to traffic from cloudflared")
	}

	tracing.EndWithStatusCode(ttfbSpan, resp.StatusCode)
	defer func() { _ = resp.Body.Close() }()

	headers := make(http.Header, len(resp.Header))
	// copy headers
	for k, v := range resp.Header {
		headers[k] = v
	}

	// Add spans to response header (if available)
	tr.AddSpans(headers)

	err = w.WriteRespHeaders(resp.StatusCode, headers)
	if err != nil {
		return errors.Wrap(err, "Error writing response header")
	}

	if resp.StatusCode == http.StatusSwitchingProtocols {
		rwc, ok := resp.Body.(io.ReadWriteCloser)
		if !ok {
			return errors.New("internal error: unsupported connection type")
		}
		defer func() { _ = rwc.Close() }()

		eyeballStream := &bidirectionalStream{
			writer: w,
			reader: tr.Body,
		}

		stream.Pipe(eyeballStream, rwc, logger)
		return nil
	}

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Check whether the end client actually cancelled/aborted the request; this is usually benign client disconnect noise.
  2. Verify network stability between cloudflared and Cloudflare edge (look for repeated reconnects in the log).
  3. Inspect origin response headers for invalid values (control characters, oversized headers) that fail transport encoding.
  4. Retry the request; a one-off error during an edge reconnect is transient.
Defensive patterns

Strategy: retry

Validate before calling

// validate origin headers before relay: reject control chars
for k, vs := range resp.Header {
    for _, v := range vs {
        if strings.ContainsAny(v, "\r\n\x00") {
            return fmt.Errorf("invalid header value for %s", k)
        }
    }
}

Try / catch

if err := w.WriteRespHeaders(resp.StatusCode, headers); err != nil {
    // log at debug: usually client/edge disconnect, not actionable
    log.Debug().Err(err).Msg("client disconnected before headers written")
    return err
}

Prevention

When it happens

Trigger: w.WriteRespHeaders(resp.StatusCode, headers) returns an error — typically because the underlying stream/connection to the edge is closed, reset, or the headers cannot be encoded on the transport.

Common situations: Client disconnected or page reload before response headers were sent; edge connection dropped due to network interruption; invalid/duplicate hop-by-hop headers from the origin causing encoding failure on the tunnel transport.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/b5de096bc43412a9. Report an issue: GitHub.