JuliusBrussee/caveman · error

rewriter: %s: nil response

Error message

rewriter: %s: nil response

What it means

The rewriter Client's injected doer (caller-supplied http.RoundTripper) returned a nil *http.Response with a nil error, which is a contract violation of http.Client/RoundTripper. The explicit check converts what would be a panic in the proxy hot path into an error.

Source

Thrown at rewriter/provider.go:193

		return nil, fmt.Errorf("rewriter: encode request: %w", err)
	}
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(encoded))
	if err != nil {
		return nil, fmt.Errorf("rewriter: build request: %w", err)
	}
	req.Header.Set("content-type", "application/json")
	for key, value := range headers {
		req.Header.Set(key, value)
	}

	resp, err := c.doer(req)
	if err != nil {
		return nil, fmt.Errorf("rewriter: %s: %w", endpoint, err)
	}
	// An injected doer is caller code; a nil response or body must surface as an
	// error rather than a panic inside the proxy hot path.
	if resp == nil {
		return nil, fmt.Errorf("rewriter: %s: nil response", endpoint)
	}
	if resp.Body == nil {
		resp.Body = http.NoBody
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		detail, _ := io.ReadAll(io.LimitReader(resp.Body, maxErrorBody))
		return nil, fmt.Errorf("rewriter: %s: status %d: %s", endpoint, resp.StatusCode, strings.TrimSpace(string(detail)))
	}
	raw, err := io.ReadAll(io.LimitReader(resp.Body, maxProviderResponseBody+1))
	if err != nil {
		return nil, fmt.Errorf("rewriter: read response: %w", err)
	}
	if len(raw) > maxProviderResponseBody {
		return nil, fmt.Errorf("rewriter: response exceeds %d bytes", maxProviderResponseBody)
	}
	return raw, nil

View on GitHub (pinned to 766dce6b13)

Solutions

  1. Fix the injected doer so it never returns (nil, nil)
  2. Return an error from the custom RoundTripper on failure paths
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at rewriter/provider.go:193 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18). Data as JSON: /api/errors/b2dd135b8e7032fc. Report an issue: GitHub.