JuliusBrussee/caveman · error
compat upstream
Error message
compat upstream %q: %w
What it means
NewNamedWithWireDialect wraps ValidateWireDialect failures with the offending mount name: "compat upstream %q: %w". It is raised when creating a named compat mount whose wire_dialect is neither "anthropic" nor empty, so startup or the test harness cannot construct the adapter.
Solutions
- Correct the wire_dialect for the named mount to "anthropic" or drop it (empty = OpenAI shape).
- The wrapped message names the mount (name in %q) — fix that mount's entry in config.
- If constructing programmatically, validate with providers.ValidateWireDialect (or openaicompat.ValidateWireDialect) before calling NewNamedWithWireDialect.
- Run the config validation (validateCompat path) at startup to catch this before serving traffic.
Example fix
// before
adapter, err := openaicompat.NewNamedWithWireDialect("claude", url, "openai-shape")
// after
adapter, err := openaicompat.NewNamedWithWireDialect("claude", url, "anthropic") Defensive patterns
Strategy: validation
Validate before calling
if d := mount.WireDialect; d != "" && d != "anthropic" {
return fmt.Errorf("mount %q: wire_dialect %q not supported", mount.Name, d)
} Try / catch
adapter, err := openaicompat.NewNamedWithWireDialect(name, baseURL, dialect)
if err != nil {
return nil, fmt.Errorf("constructing compat mount: %w", err)
} Prevention
- Validate dialects at config-load time, before constructing adapters.
- Keep dialect strings in a small typed constant set.
- Test mount construction in CI with the real config file.
When it happens
Trigger: Calling NewNamedWithWireDialect(name, baseURL, dialect, ...) or buildAdapters on config with an invalid dialect string; also exercised by the dialect stream/non-stream tests that pass an unknown dialect.
Common situations: Invalid wire_dialect in the mounts config loaded at startup; unit/integration tests constructing mounts with an intentionally bad dialect; config templating injecting a dialect variable that is empty-but-nonstandard (e.g. "none").
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- compat upstream name
- compat upstream name
- compat upstream base_url
- compat upstream forward_headers
- provider has no configured upstream URL
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/9b4d5913dad8acd8.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/providers/openaicompat/openaicompat.go:374
// on the mount. It changes two things and nothing else:
//
// - USAGE ACCOUNTING parses with the Anthropic dialect (Base.UsageProvider):
// the usage block reports input_tokens EXCLUSIVE of cache reads/writes, so
// the OpenAI-shape contradiction check reads a warm cache as malformed and
// drops every such row from token accounting (issue #1026).
// - COMPRESSION ZONES follow the Anthropic Messages grammar on Messages-path
// requests and keep the OpenAI grammar on every other path (see
// anthropicWireZones): the Anthropic extractor keys the live/frozen
// boundary on the request's own cache_control breakpoints.
//
// Routing, header mapping, telemetry provider, and pricing keep the mount's
// openai_compatible identity in every dialect.
func NewNamedWithWireDialect(name, baseURL, wireDialect string, forwardHeaders ...string) (providers.Adapter, error) {
if err := ValidateName(name); err != nil {
return nil, err
}
if err := ValidateWireDialect(wireDialect); err != nil {
return nil, fmt.Errorf("compat upstream %q: %w", name, err)
}
baseURL = strings.TrimSpace(baseURL)
if err := ValidateBaseURL(baseURL); err != nil {
return nil, fmt.Errorf("compat upstream %q base_url: %w", name, err)
}
if err := ValidateForwardHeaders(forwardHeaders); err != nil {
return nil, fmt.Errorf("compat upstream %q forward_headers: %w", name, err)
}
prefix := "/compat/" + name
return namedAdapter{
Base: providers.Base{
Provider: "openai_compatible",
BaseURL: baseURL,
Routes: []string{prefix + "/"},
UsageProvider: wireDialectUsageProvider[wireDialect],
},
prefix: prefix,
forwardHeaders: append([]string(nil), forwardHeaders...),View on GitHub (pinned to 3ee70a1026)