JuliusBrussee/caveman · error
compat upstream %q: base_url: %w
Error message
compat upstream %q: base_url: %w
What it means
validateCompat passes base_url through openaicompat.ValidateBaseURL, which parses it as an absolute URL for a compat upstream. The %w chain preserves the underlying parse error, so the message tells you exactly why the URL is unusable (missing scheme, unparseable, wrong scheme).
Source
Thrown at proxy/internal/config/config.go:251
// 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)
}
}
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",
}
// Credential returns the provider credential resolved from the environment.
// Empty means the caller must fail closed or use an explicit inbound credential.
// Bedrock bearer keys are PAYG credentials even though their wire scheme isView on GitHub (pinned to 27d5a3981a)
Solutions
- Prefix the scheme: base_url: https://openrouter.ai/api/v1
- Use http:// only for deliberate local test doubles; https:// for real upstreams
- Trim stray quotes, spaces, or newlines from env-provided URLs
- Read the wrapped (%w) parse error text — it names the exact URL defect
Example fix
# before
compat:
openrouter:
base_url: openrouter.ai/api/v1 # Error[1064]: no scheme
# after
compat:
openrouter:
base_url: https://openrouter.ai/api/v1 Defensive patterns
Strategy: validation
Validate before calling
func usableBaseURL(raw string) bool {
u, err := url.Parse(strings.TrimSpace(raw))
return err == nil && u.IsAbs() && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}
for name, up := range cfg.Compat {
if !usableBaseURL(up.BaseURL) { /* reject config */ }
} Prevention
- Always include the https:// scheme when pasting provider URLs
- Trim and sanity-check env-provided URLs before writing config
- Run ValidateBaseURL (openaicompat package) on generated configs
When it happens
Trigger: base_url like 'openrouter.ai/api/v1' (no scheme), 'ftp://...' (wrong scheme), a URL with spaces or control characters, or one that net/url.Parse rejects (e.g. embedded credentials with invalid escapes).
Common situations: Omitting https:// when pasting from a browser bar; trailing '/v1' path confusion is fine but scheme omission is not; env var with stray quotes or newline characters.
Related errors
- compat upstream %q: %w
- compat upstream %q: base_url is required
- cave_budget_denomination_ambiguous
- cave_budget_max_invalid
- cave_budget_output_floor_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/e8416d745dc89c43.
Report an issue: GitHub.