JuliusBrussee/caveman · error

upstream body exceeds %d bytes

Error message

upstream body exceeds %d bytes

What it means

readUpstreamBody enforces CAVE_MAX_RESPONSE_BUFFER_BYTES (default 64 MiB) as a memory bound when draining a non-streaming upstream response; a body over the cap is refused rather than buffered unbounded. Provider JSON never legitimately approaches this limit.

Source

Thrown at proxy/internal/gateway/proxy.go:1573

func labelOrDefault(v, fallback string) string {
	if v == "" {
		return fallback
	}
	return v
}

// readUpstreamBody drains a non-streaming upstream body in full. The cap only
// bounds memory; a provider JSON document never approaches it.
func readUpstreamBody(resp *http.Response) ([]byte, error) {
	defer resp.Body.Close()
	limit := int64(env.Int("CAVE_MAX_RESPONSE_BUFFER_BYTES", 64<<20))
	data, err := io.ReadAll(io.LimitReader(resp.Body, limit+1))
	if err != nil {
		return nil, err
	}
	if int64(len(data)) > limit {
		return nil, fmt.Errorf("upstream body exceeds %d bytes", limit)
	}
	return data, nil
}

type countingWriter struct {
	w           http.ResponseWriter
	n           int64
	firstByteAt time.Time
}

func (c *countingWriter) Write(p []byte) (int, error) {
	if c.firstByteAt.IsZero() && len(p) > 0 {
		c.firstByteAt = time.Now()
	}
	n, err := c.w.Write(p)
	c.n += int64(n)
	return n, err
}

View on GitHub (pinned to df2ccd85c9)

Solutions

  1. Raise CAVE_MAX_RESPONSE_BUFFER_BYTES if legitimately huge responses are expected
  2. Use streaming mode for responses that exceed the buffer cap
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at proxy/internal/gateway/proxy.go:1576 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of JuliusBrussee/caveman@df2ccd85c9 (2026-08-27). Data as JSON: /api/errors/bc1bdfda54fc5021. Report an issue: GitHub.