JuliusBrussee/caveman · error
azure request has duplicate api-version values
Error message
azure request has duplicate api-version values
What it means
On the Foundry Models v1 inference routes (/openai/v1/chat/completions, /openai/v1/responses), validateAzureRequest reads all api-version query parameters and rejects the request if more than one is present. Duplicate query keys make version selection ambiguous, so the proxy refuses rather than pick one. This guard runs in ResolveUpstreamURL before any upstream dial.
Source
Thrown at proxy/providers/azureopenai/azure_routing.go:42
"2025-04-01-preview",
"preview",
"latest",
}
// ResolveUpstreamURL validates either the legacy deployment route or the
// current Foundry Models v1 inference route before resolving upstream.
func (a Adapter) ResolveUpstreamURL(ctx context.Context, req *http.Request, route providers.RouteContext) (*url.URL, error) {
if err := validateAzureRequest(req.URL); err != nil {
return nil, err
}
return a.Base.ResolveUpstreamURL(ctx, req, route)
}
func validateAzureRequest(u *url.URL) error {
if foundryV1InferenceRoute(u.Path) {
versions := u.Query()["api-version"]
if len(versions) > 1 {
return fmt.Errorf("azure request has duplicate api-version values")
}
if len(versions) == 1 && versions[0] != "v1" && versions[0] != "preview" {
return fmt.Errorf("azure Foundry api-version %q is not supported", versions[0])
}
return nil
}
if !legacyChatCompletionsRoute(u.Path) {
return fmt.Errorf("azure legacy inference path %q is not supported", u.Path)
}
versions := u.Query()["api-version"]
if len(versions) > 1 {
return fmt.Errorf("azure request has duplicate api-version values")
}
version := ""
if len(versions) == 1 {
version = versions[0]
}
if version == "" {View on GitHub (pinned to 27d5a3981a)
Solutions
- Send exactly one api-version (for Foundry v1 routes: 'v1' or 'preview').
- Audit the client for double-appending: disable the SDK's automatic api-version or remove your manual query parameter.
- Build URLs with a params map (key set once) instead of string concatenation.
Example fix
# before curl "$PROXY/azure/openai/v1/chat/completions?api-version=v1&api-version=preview" # after curl "$PROXY/azure/openai/v1/chat/completions?api-version=v1"
Defensive patterns
Strategy: validation
Validate before calling
vals := req.URL.Query()["api-version"]
if len(vals) > 1 {
return fmt.Errorf("duplicate api-version values %v; send exactly one", vals)
} Type guard
func hasSingleAPIVersion(u *url.URL) bool {
return len(u.Query()["api-version"]) <= 1
} Try / catch
if err := validateAzureRequest(req.URL); err != nil {
if strings.Contains(err.Error(), "duplicate api-version") {
http.Error(w, "send exactly one api-version query parameter", http.StatusBadRequest)
return
}
http.Error(w, err.Error(), http.StatusBadRequest)
} Prevention
- Set api-version in exactly one layer (SDK config OR manual param, never both).
- Build URLs from a param map, not string concatenation.
- Log RawQuery at the edge to catch double-appending middleware.
When it happens
Trigger: A URL like /azure/openai/v1/chat/completions?api-version=v1&api-version=preview — usually caused by a client SDK appending api-version while the caller also set it, or a URL-builder appending the parameter twice.
Common situations: Combining an SDK that auto-appends api-version with hand-added query params; retry/rewrite middleware that appends the param without checking; string concatenation building URLs in scripts.
Related errors
- azure request missing api-version
- azure Foundry api-version %q is not supported
- azure legacy inference path %q is not supported
- cachebench: nil corpus reader
- message exceeds byte limit
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/d76136f0cd989915.
Report an issue: GitHub.