JuliusBrussee/caveman · error
provider upstream URL must be an absolute URL with a host
Error message
provider %q upstream URL must be an absolute URL with a host
What it means
The caveman proxy's OpenAI-compatible adapter validates the configured upstream base URL in parseBaseURL (openaicompat.go:522) before joining request paths onto it. This error fires when the URL either has no scheme (relative URL), or parses to an empty host (e.g. 'https:///v1' or 'http://'). The adapter cannot build a deterministic upstream endpoint without an absolute host, so it fails closed.
Solutions
- Add the missing scheme and host so the value is a full absolute URL, e.g. change '/v1' to 'https://api.example.com/v1'.
- Check the config file and any CAVE_*_BASE_URL environment variable overrides for a truncated or empty host segment and repair it.
- Run the adapter's ValidateBaseURL (ValidateBaseURL(raw, "compat")) at startup or in a unit test to fail fast on the malformed value.
Example fix
// before (caveman.yaml) base_url: /v1 # after base_url: https://api.openai-compatible.example.com/v1
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(strings.TrimSpace(cfg.BaseURL))
if err != nil || !u.IsAbs() || u.Host == "" || u.Hostname() == "" || (u.Scheme != "http" && u.Scheme != "https") {
return fmt.Errorf("provider %q base URL must be an absolute http(s) URL with a host", name)
} Type guard
func isValidBaseURL(raw string) bool {
u, err := url.Parse(strings.TrimSpace(raw))
return err == nil && u.IsAbs() && u.Host != "" && (u.Scheme == "http" || u.Scheme == "https")
} Try / catch
base, err := parseBaseURL(cfg.BaseURL, provider)
if err != nil {
log.Fatalf("invalid base_url for %s: %v — expected https://host[:port]/path", provider, err)
} Prevention
- Always write base URLs with an explicit https:// scheme and host in config files.
- Call ValidateBaseURL at startup so a bad base_url fails before the first request.
- Never build a base URL by concatenating path fragments; keep scheme+host together.
- Audit CAVE_*_BASE_URL environment overrides when config errors appear.
When it happens
Trigger: Calling ResolveUpstreamURL or ValidateBaseURL when the provider's configured base URL is a relative path like '/v1', a scheme-only string like 'https://', or a URL where the host portion is empty (e.g. 'https:///api').
Common situations: A caveman.yaml compat-provider entry where the base_url was pasted without the 'https://' prefix, an env-var override (e.g. CAVE_..._BASE_URL) left partially filled, or a YAML value starting with '/' interpreted as a path. Also common when a trailing segment was accidentally kept and the host deleted during editing.
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
- provider upstream URL must not include a fragment
- aes cipher
- budget is below CCR storage minimum
- githubapp: invalid base URL
- native session key length =
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/89077585981d47c6.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/providers/openaicompat/openaicompat.go:523
return fmt.Errorf("ambiguous escaped path sequence %s", escape)
}
}
return nil
}
func parseBaseURL(raw, provider string) (*url.URL, error) {
if strings.TrimSpace(raw) == "" {
return nil, fmt.Errorf("provider %q has no configured upstream URL", provider)
}
u, err := url.Parse(strings.TrimSpace(raw))
if err != nil {
return nil, err
}
if u.Scheme != "http" && u.Scheme != "https" {
return nil, fmt.Errorf("provider %q upstream URL scheme %q is not allowed", provider, u.Scheme)
}
if !u.IsAbs() || u.Host == "" || u.Hostname() == "" {
return nil, fmt.Errorf("provider %q upstream URL must be an absolute URL with a host", provider)
}
if u.User != nil {
return nil, fmt.Errorf("provider %q upstream URL must not include userinfo", provider)
}
if u.Fragment != "" {
return nil, fmt.Errorf("provider %q upstream URL must not include a fragment", provider)
}
if err := validatePathComponents(u.Path, u.RawPath); err != nil {
return nil, fmt.Errorf("provider %q upstream URL path rejected: %w", provider, err)
}
return u, nil
}
View on GitHub (pinned to 3ee70a1026)