{"record":{"id":"fbf7d3cb2ec2aa3f","repo":"JuliusBrussee/caveman","slug":"azure-foundry-api-version-q-is-not-supported","errorCode":null,"errorMessage":"azure Foundry api-version %q is not supported","messagePattern":"azure Foundry api-version %q is not supported","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/providers/azureopenai/azure_routing.go","lineNumber":45,"sourceCode":"}\n\n// ResolveUpstreamURL validates either the legacy deployment route or the\n// current Foundry Models v1 inference route before resolving upstream.\nfunc (a Adapter) ResolveUpstreamURL(ctx context.Context, req *http.Request, route providers.RouteContext) (*url.URL, error) {\n\tif err := validateAzureRequest(req.URL); err != nil {\n\t\treturn nil, err\n\t}\n\treturn a.Base.ResolveUpstreamURL(ctx, req, route)\n}\n\nfunc validateAzureRequest(u *url.URL) error {\n\tif foundryV1InferenceRoute(u.Path) {\n\t\tversions := u.Query()[\"api-version\"]\n\t\tif len(versions) > 1 {\n\t\t\treturn fmt.Errorf(\"azure request has duplicate api-version values\")\n\t\t}\n\t\tif len(versions) == 1 && versions[0] != \"v1\" && versions[0] != \"preview\" {\n\t\t\treturn fmt.Errorf(\"azure Foundry api-version %q is not supported\", versions[0])\n\t\t}\n\t\treturn nil\n\t}\n\tif !legacyChatCompletionsRoute(u.Path) {\n\t\treturn fmt.Errorf(\"azure legacy inference path %q is not supported\", u.Path)\n\t}\n\tversions := u.Query()[\"api-version\"]\n\tif len(versions) > 1 {\n\t\treturn fmt.Errorf(\"azure request has duplicate api-version values\")\n\t}\n\tversion := \"\"\n\tif len(versions) == 1 {\n\t\tversion = versions[0]\n\t}\n\tif version == \"\" {\n\t\treturn fmt.Errorf(\"azure request missing api-version\")\n\t}\n\tif !apiVersionAllowed(version) {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/proxy/providers/azureopenai/azure_routing.go#L27-L63","documentation":"For Azure Foundry v1 inference routes, the only accepted api-version values are 'v1' and 'preview' (these are GA labels of the Models API, not dated versions). If exactly one api-version is present and it is neither — e.g. a dated legacy version like 2024-10-21 — the request is rejected before upstream resolution. The GA v1 surface intentionally does not accept legacy dated versions.","triggerScenarios":"Calling /azure/openai/v1/chat/completions?api-version=2024-10-21 — mixing the legacy deployment-style dated version with the new v1 route; SDK defaults tuned for the old API reused on the Foundry route.","commonSituations":"Migrating a client from the legacy deployments/... route to the v1 route while keeping the old api-version; SDK configuration that always stamps a dated version; docs/examples written for the legacy surface.","solutions":["On /openai/v1/... routes send api-version=v1 (or 'preview'), or omit it entirely.","If you need a dated version, use the legacy route /azure/openai/deployments/<deployment>/chat/completions?api-version=<date> instead.","Update the client SDK config so it stops injecting its default dated version."],"exampleFix":"# before\ncurl \"$PROXY/azure/openai/v1/chat/completions?api-version=2024-10-21\"\n\n# after\ncurl \"$PROXY/azure/openai/v1/chat/completions?api-version=v1\"","handlingStrategy":"validation","validationCode":"const foundryPath = \"/openai/v1/chat/completions\" // or /openai/v1/responses\nv := u.Query().Get(\"api-version\")\nif strings.HasPrefix(strings.TrimPrefix(u.Path, \"/azure\"), \"/openai/v1/\") {\n    if v != \"\" && v != \"v1\" && v != \"preview\" {\n        return fmt.Errorf(\"Foundry v1 routes accept only api-version=v1|preview, got %q\", v)\n    }\n}","typeGuard":"func foundryVersionOK(v string) bool {\n    return v == \"\" || v == \"v1\" || v == \"preview\"\n}","tryCatchPattern":"if err := validateAzureRequest(req.URL); err != nil {\n    if strings.Contains(err.Error(), \"Foundry api-version\") {\n        http.Error(w, \"use api-version=v1 or preview on /openai/v1/ routes (dated versions belong to the legacy deployments route)\", http.StatusBadRequest)\n        return\n    }\n    http.Error(w, err.Error(), http.StatusBadRequest)\n}","preventionTips":["Treat v1-route versions ('v1'/'preview') and legacy dated versions as separate conventions.","Update SDK defaults when migrating from the legacy route to v1.","Encode the route/version pairing in client configuration templates."],"tags":["go","azure","versioning","validation"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}