JuliusBrussee/caveman · error
compat upstream name
Error message
compat upstream name %q is reserved
What it means
After passing the name grammar, ValidateName rejects the reserved names "stub" and "openai-compatible", which are the built-in default compat mounts. Using them for a custom mount would collide with the built-in /compat/stub and /compat/openai-compatible routes.
Solutions
- Rename the mount to something unique, e.g. "my-openai" or "acme-proxy".
- Keep using the built-in /compat/openai-compatible mount instead of defining a custom one with that name.
- Use "stub" only for the built-in test stub, never in production config.
- Run the startup config validation and rename any entry it flags as reserved.
Example fix
# before name = "openai-compatible" # after name = "my-openai-compatible"
Defensive patterns
Strategy: validation
Validate before calling
var reserved = map[string]bool{"stub": true, "openai-compatible": true}
if reserved[mount.Name] {
return fmt.Errorf("mount name %q is reserved; pick a unique name", mount.Name)
} Try / catch
if err := openaicompat.ValidateName(name); err != nil {
return nil, fmt.Errorf("choose a non-reserved mount name: %w", err)
} Prevention
- Never name custom mounts "stub" or "openai-compatible".
- Prefix custom mount names with your org, e.g. "acme-openai".
- Keep built-in mounts and custom mounts in separate config sections.
When it happens
Trigger: Configuring a named compat mount with name = "stub" or "openai-compatible" and loading it via validateCompat/NewNamedWithWireDialect.
Common situations: Copying the built-in default mount entry to customize it without renaming; config examples that use "stub" as a placeholder name left unchanged.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- compat upstream name
- compat upstream base_url
- compat upstream forward_headers
- compat upstream
- provider has no configured upstream URL
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/487c21ca5b20b72f.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/providers/openaicompat/openaicompat.go:426
// constructs. x-forwarded-*/forwarded/x-real-ip would let a caller
// choose the client address an upstream rate-limits or allowlists on.
case "host", "connection", "keep-alive", "proxy-connection", "proxy-authorization", "proxy-authenticate", "te", "trailer", "transfer-encoding", "upgrade", "content-length", "expect",
"authorization", "x-api-key", "api-key", "x-goog-api-key", "x-goog-user-project", "cookie", "set-cookie",
"forwarded", "x-forwarded-for", "x-forwarded-host", "x-forwarded-proto", "x-forwarded-port", "x-real-ip",
"user-agent", "content-type":
return fmt.Errorf("header %q cannot be forwarded", name)
}
}
return nil
}
func ValidateName(name string) error {
if !validName.MatchString(name) {
return fmt.Errorf("compat upstream name %q must match [a-z0-9][a-z0-9._-]{0,63}", name)
}
switch name {
case "stub", "openai-compatible":
return fmt.Errorf("compat upstream name %q is reserved", name)
default:
return nil
}
}
func ValidateBaseURL(raw string) error {
_, err := parseBaseURL(raw, "compat")
return err
}
// ResolveUpstreamURL intentionally ignores RouteContext.BaseURL. Named mounts
// are configured as independent static upstreams (`compat:` in standalone or
// CAVE_COMPAT_UPSTREAMS in managed mode); applying the generic project
// openai_compatible override here would collapse every named route onto one
// target. The default /compat/ adapter is the route that honors BaseURL.
func (a namedAdapter) ResolveUpstreamURL(_ context.Context, req *http.Request, _ providers.RouteContext) (*url.URL, error) {
if req == nil || req.URL == nil {
return nil, fmt.Errorf("compat request URL is missing")View on GitHub (pinned to 3ee70a1026)