JuliusBrussee/caveman · error

compat upstream : forward_headers

Error message

compat upstream %q: forward_headers: %w

What it means

The compat upstream's forward_headers list failed openaicompat.ValidateForwardHeaders, wrapped after the "forward_headers: " prefix. Forward headers are passed through to the upstream verbatim, so names/values must satisfy the validator's rules (e.g. valid header names, no forbidden headers).

Solutions

  1. Remove or correct the offending header named in the wrapped error.
  2. Keep only safe, custom headers (e.g. "X-Request-Id") in forward_headers.
  3. Consult openaicompat.ValidateForwardHeaders for the exact allowed header-name rules.

Example fix

// before
forward_headers = ["Authorization", "X-Tenant"]
// after
forward_headers = ["X-Tenant"]
Defensive patterns

Strategy: validation

Validate before calling

if err := openaicompat.ValidateForwardHeaders(upstream.ForwardHeaders); err != nil {
    return fmt.Errorf("compat upstream %q forward_headers invalid: %w", name, err)
}

Prevention

When it happens

Trigger: Configuring forward_headers on a compat upstream with an entry that openaicompat.ValidateForwardHeaders rejects — e.g. an invalid header name, a forbidden/hop-by-hop header, or a malformed list element — then calling Load.

Common situations: Forwarding headers like Authorization or Host that are handled internally; header names with spaces or non-token characters; YAML/TOML list accidentally containing empty strings.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/e0fec8c25dac5b78. Report an issue: GitHub.

Appendix: source

Thrown at proxy/internal/config/config.go:464

	if configured := c.BaseURL("bedrock", ""); configured != "" {
		return configured
	}
	return fmt.Sprintf("https://bedrock-runtime.%s.amazonaws.com", c.BedrockRegion())
}

func (c Config) validateCompat() error {
	for name, upstream := range c.Compat {
		if err := openaicompat.ValidateName(name); err != nil {
			return fmt.Errorf("compat upstream %q: %w", name, err)
		}
		if strings.TrimSpace(upstream.BaseURL) == "" {
			return fmt.Errorf("compat upstream %q: base_url is required", name)
		}
		if err := openaicompat.ValidateBaseURL(upstream.BaseURL); err != nil {
			return fmt.Errorf("compat upstream %q: base_url: %w", name, err)
		}
		if err := openaicompat.ValidateForwardHeaders(upstream.ForwardHeaders); err != nil {
			return fmt.Errorf("compat upstream %q: forward_headers: %w", name, err)
		}
		if err := openaicompat.ValidateWireDialect(upstream.WireDialect); err != nil {
			return fmt.Errorf("compat upstream %q: %w", name, err)
		}
	}
	return nil
}

// providerEnvKey maps a provider name to the BYOK environment variable that
// holds its API key.
var providerEnvKey = map[string]string{
	"anthropic":         "ANTHROPIC_API_KEY",
	"openai":            "OPENAI_API_KEY",
	"gemini":            "GEMINI_API_KEY",
	"azure_openai":      "AZURE_OPENAI_API_KEY",
	"openai_compatible": "OPENAI_COMPAT_API_KEY",
}

View on GitHub (pinned to 3ee70a1026)