JuliusBrussee/caveman · error
compat route %q does not match prefix %q
Error message
compat route %q does not match prefix %q
What it means
Thrown by namedAdapter.ResolveUpstreamURL when the request path does not start with the adapter's configured prefix plus a slash (e.g. "/compat/myupstream/"). Named mounts own a distinct path prefix; a request that reaches the wrong named adapter, or omits the trailing mount segment, is rejected rather than proxied with an unintended path.
Source
Thrown at proxy/providers/openaicompat/openaicompat.go:236
// 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")
}
if err := validateCompatPath(req.URL.Path, req.URL.RawPath); err != nil {
return nil, err
}
base, err := parseBaseURL(a.BaseURL, a.Provider)
if err != nil {
return nil, err
}
if !strings.HasPrefix(req.URL.Path, a.prefix+"/") {
return nil, fmt.Errorf("compat route %q does not match prefix %q", req.URL.Path, a.prefix+"/")
}
path := strings.TrimPrefix(req.URL.Path, a.prefix)
base.Path = joinCompatPath(base.Path, path)
base.RawPath = ""
base.RawQuery = joinCompatQuery(base.RawQuery, req.URL.RawQuery)
return base, nil
}
// ValidateRequestPath rejects ambiguous path encodings before adapter selection.
// Gateways call this with the original URL (including RawPath), while the
// adapter MatchRoute/ResolveUpstreamURL checks provide a second fail-closed
// boundary for direct callers.
func ValidateRequestPath(u *url.URL) error {
if u == nil {
return fmt.Errorf("request URL is missing")
}
if !strings.HasPrefix(u.Path, "/compat/") {
return nilView on GitHub (pinned to 27d5a3981a)
Solutions
- Send requests to the full path under the named mount: /compat/<name>/<rest-of-path> (e.g. /compat/groq/v1/chat/completions).
- Verify the named adapter's configured prefix matches the route the gateway dispatches to it — both come from the same compat upstream definition.
- If the intent was the default /compat/ behavior (provider BaseURL override), use the default Adapter, not a namedAdapter.
Example fix
# before: request to bare mount handled by named adapter POST /compat/v1/chat/completions # after: request under the named mount POST /compat/groq/v1/chat/completions
Defensive patterns
Strategy: validation
Validate before calling
func matchesNamedMount(path, prefix string) bool {
return strings.HasPrefix(path, prefix+"/")
} Try / catch
Return 404 at the gateway for the mismatched path; log the adapter's prefix and the request path together to make the misroute obvious.
Prevention
- Derive the named adapter's prefix and the gateway route from the same config value, never two copies.
- When renaming a compat upstream, update routes, config, and client docs in one change.
- Assert one positive and one negative path per named mount in routing tests.
When it happens
Trigger: A named adapter configured with prefix "/compat/groq" receiving a request for "/compat/groq" (no trailing slash + suffix), "/compat/openrouter/...", or "/compat/..." — any path lacking the exact "prefix + "/"" start.
Common situations: Gateway route table mapping two named mounts to each other's adapters; renaming a mount in config while the route registration kept the old prefix; a client hitting the bare mount path but the named adapter being selected.
Related errors
- compat route %q does not match default /compat/ mount
- provider %q has no configured upstream URL
- provider %q upstream URL must be absolute
- bedrock configured endpoint kind %q does not allow request k
- cave_vercel_terminal_failure
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/d4eb230f89d49aea.
Report an issue: GitHub.