JuliusBrussee/caveman · error

compat upstream : base_url

Error message

compat upstream %q: base_url: %w

What it means

The compat upstream's base_url was non-empty but failed openaicompat.ValidateBaseURL, with the underlying reason wrapped after the "base_url: " prefix. The URL must be a well-formed HTTP(S) endpoint suitable for an OpenAI-compatible API base.

Solutions

  1. Fix base_url to a well-formed absolute URL with an http/https scheme, e.g. "https://api.example.com/v1".
  2. Check the wrapped error text for the specific rule violated and correct that aspect (scheme, host, parsing).
  3. Trim whitespace/quotes from the configured value.

Example fix

// before
base_url = "api.example.com/v1"
// after
base_url = "https://api.example.com/v1"
Defensive patterns

Strategy: validation

Validate before calling

if err := openaicompat.ValidateBaseURL(upstream.BaseURL); err != nil {
    return fmt.Errorf("compat upstream %q base_url invalid: %w", name, err)
}
// or pre-check:
if u, err := url.Parse(upstream.BaseURL); err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("base_url must be an absolute http(s) URL")
}

Prevention

When it happens

Trigger: Setting base_url to a malformed URL — missing scheme ("api.example.com/v1"), unsupported scheme ("ftp://..."), garbage like "localhost port 8080", or a value that fails the validator's URL rules — then calling Load.

Common situations: Omitting "https://" when pasting a host; including spaces or trailing junk; using a unix-socket or internal scheme the validator does not accept.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

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

// Runtime endpoint from BedrockRegion. Callers never need to paste a raw URL for
// the normal first-party path.
func (c Config) BedrockBaseURL() string {
	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",

View on GitHub (pinned to 3ee70a1026)