JuliusBrussee/caveman · error
provider upstream URL path rejected
Error message
provider %q upstream URL path rejected: %w
What it means
This is a wrapped error: parseBaseURL runs validatePathComponents on the configured base URL's Path/RawPath (openaicompat.go:531) and re-wraps any rejection as 'provider %q upstream URL path rejected: %w'. validatePathComponents forbids backslashes, empty interior segments (repeated '//'), dot segments ('.'/'..'), and ambiguous escaped sequences (%2f, %5c, %2e) so a URL cannot change route identity after another decoder or proxy hop.
Solutions
- Read the wrapped cause at the end of the message and remove the offending construct (backslash, '//', '.'/'..', or %2f/%5c/%2e) from the base URL path.
- Normalize the path to plain '/'-separated segments and confirm it matches the vendor's documented base path.
- Re-run ValidateBaseURL; also check ValidateRequestPath on inbound /compat/ routes, which applies the same rules to request paths.
Example fix
// before base_url: https://api.example.com/v1/../prod // after base_url: https://api.example.com/prod
Defensive patterns
Strategy: validation
Validate before calling
u, _ := url.Parse(raw)
if err := validatePathComponents(u.Path, u.RawPath); err != nil {
return fmt.Errorf("base URL path rejected: %w — remove backslashes, '//' runs, dot segments, and %2f/%5c/%2e escapes", err)
} Type guard
func hasCleanPath(raw string) bool {
u, err := url.Parse(raw)
return err == nil && validatePathComponents(u.Path, u.RawPath) == nil
} Try / catch
if _, err := parseBaseURL(raw, provider); err != nil {
var cause error
if errors.As(err, &cause) || true {
log.Fatalf("fix the base URL path (see wrapped cause): %v", err)
}
} Prevention
- Write base URL paths as plain '/'-separated lowercase segments; never use '..' or '//'.
- Avoid escaped slashes/percent tricks in base URLs — they change route identity across decoders.
- Use forward-slash paths even when copying from Windows tooling.
- Reuse ValidateRequestPath on inbound routes to catch the same issues symmetrically.
When it happens
Trigger: Call ResolveUpstreamURL or ValidateBaseURL with a base URL whose path contains e.g. 'https://api.example.com//v1', '.../v1/../v2', a backslash ('https://api.example.com\v1'), or an escaped '%2f'/'%2e' in RawPath. The %w verb reveals the specific cause (backslash / repeated separators / dot segments / ambiguous escape).
Common situations: Hand-edited YAML with double slashes, Windows-style paths pasted with backslashes, or intentionally obfuscated/redirect-style URLs that use encoded slashes to slip past path-based routing.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- dot segments are not allowed in path
- provider upstream URL must not include userinfo
- ssrf: host is blocked (loopback)
- ambiguous escaped path sequence
- awscreds: AWS_CONTAINER_CREDENTIALS_FULL_URI is not a valid…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/b0b727b79e2a1bac.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/providers/openaicompat/openaicompat.go:532
}
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)