JuliusBrussee/caveman · error
compat route does not match default /compat/ mount
Error message
compat route %q does not match default /compat/ mount
What it means
The openaicompat adapter only serves requests mounted under the /compat/ path prefix; ResolveUpstreamURL rejects any request whose URL path does not start with /compat/. The error reports the offending path so you can see which route was misrouted to the compat provider.
Solutions
- Route the request through a path beginning with /compat/ (e.g. /compat/<mount-name>/v1/...).
- If you need a custom prefix, use the named-mount mechanism (NewNamedWithWireDialect / config named mounts) instead of relying on the default mount.
- Check any rewriting middleware (ingress, strip-prefix) is not removing the /compat/ segment.
- Verify the route is being dispatched to the correct adapter, not the compat one, if the path is intentionally non-compat.
Example fix
// before
http.Post("http://proxy/v1/chat/completions", ...)
// after
http.Post("http://proxy/compat/openai-compatible/v1/chat/completions", ...) Defensive patterns
Strategy: validation
Validate before calling
func isCompatRoute(u *url.URL) bool {
return u != nil && strings.HasPrefix(u.Path, "/compat/")
} Try / catch
upstream, err := adapter.ResolveUpstreamURL(ctx, req, routeCtx)
if err != nil && strings.Contains(err.Error(), "does not match default /compat/ mount") {
return fmt.Errorf("rewrite request to /compat/<mount>/... before dispatch: %w", err)
} Prevention
- Always build compat client URLs as /compat/<mount-name>/v1/...
- Audit ingress/rewrite rules for prefix stripping of /compat/.
- Use the proxy's client SDK/connector instead of hand-assembled paths.
When it happens
Trigger: An http.Request whose URL.Path lacks the /compat/ prefix (or a nil request/URL) reaches the compat adapter's ResolveUpstreamURL during route resolution.
Common situations: Mounting the openai_compatible adapter on a custom route prefix other than /compat/; a reverse-proxy rewrite strips /compat/ before the request hits the provider; programmatic adapter use invoking ResolveUpstreamURL directly with a raw path.
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
- compat route does not match prefix
- compat request URL is missing
- compat route path rejected
- compat upstream name
- compat upstream name
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/18572442082d13e9.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/providers/openaicompat/openaicompat.go:46
// keeps direct adapter users fail-closed as well.
func (a Adapter) MatchRoute(method, path string) bool {
if err := validateCompatPath(path, ""); err != nil {
return false
}
return a.Base.MatchRoute(method, path)
}
// ResolveUpstreamURL removes only the default public /compat mount before
// resolving the provider path. Named adapters and the reserved legacy routes
// keep their dedicated resolver/compatibility behavior; this method exists for
// the bare providers.openai_compatible route only.
func (a Adapter) ResolveUpstreamURL(_ context.Context, req *http.Request, route providers.RouteContext) (*url.URL, error) {
if req == nil || req.URL == nil || !strings.HasPrefix(req.URL.Path, "/compat/") {
path := ""
if req != nil && req.URL != nil {
path = req.URL.Path
}
return nil, fmt.Errorf("compat route %q does not match default /compat/ mount", path)
}
if err := validateCompatPath(req.URL.Path, req.URL.RawPath); err != nil {
return nil, err
}
// /compat/stub and /compat/openai-compatible were the original default
// routes. They share the same strict path and query handling as the bare
// mount, but retain their historical prefix stripping.
requestPath := strings.TrimPrefix(req.URL.Path, "/compat")
for _, legacy := range []string{"/stub", "/openai-compatible"} {
if hasCompatPrefix(req.URL.Path, "/compat"+legacy) {
requestPath = strings.TrimPrefix(req.URL.Path, "/compat"+legacy)
break
}
}
baseURL := a.Base.BaseURL
if route.BaseURL != "" {View on GitHub (pinned to 3ee70a1026)