JuliusBrussee/caveman · error

azure request missing api-version

Error message

azure request missing api-version

What it means

On the legacy deployment route, api-version is mandatory: Azure's legacy surface requires the dated query parameter to select API behavior, and this proxy enforces presence (after duplicate checks) before resolving upstream. A legacy request with no api-version at all fails with this error rather than being forwarded and rejected upstream.

Source

Thrown at proxy/providers/azureopenai/azure_routing.go:61

		}
		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 == "" {
		return fmt.Errorf("azure request missing api-version")
	}
	if !apiVersionAllowed(version) {
		return fmt.Errorf("azure api-version %q is not on the allowlist", version)
	}
	return nil
}

func foundryV1InferenceRoute(path string) bool {
	path = strings.TrimPrefix(path, "/azure")
	switch path {
	case "/openai/v1/chat/completions", "/openai/v1/responses":
		return true
	default:
		return false
	}
}

func legacyChatCompletionsRoute(path string) bool {

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Append a dated, allowlisted version: ?api-version=2024-10-21.
  2. Or switch to the Foundry v1 route where api-version may be omitted entirely.
  3. Centralize version selection in client config so it is never accidentally empty.

Example fix

# before
curl "$PROXY/azure/openai/deployments/gpt-4o/chat/completions"

# after
curl "$PROXY/azure/openai/deployments/gpt-4o/chat/completions?api-version=2024-10-21"
Defensive patterns

Strategy: validation

Validate before calling

if strings.HasPrefix(strings.TrimPrefix(u.Path, "/azure"), "/openai/deployments/") {
    if u.Query().Get("api-version") == "" {
        return errors.New("legacy Azure route requires ?api-version=<dated version>")
    }
}

Type guard

func legacyRouteHasVersion(u *url.URL) bool {
    legacy := strings.HasPrefix(strings.TrimPrefix(u.Path, "/azure"), "/openai/deployments/")
    return !legacy || u.Query().Get("api-version") != ""
}

Try / catch

if err := validateAzureRequest(req.URL); err != nil {
    if strings.Contains(err.Error(), "missing api-version") {
        http.Error(w, "legacy route requires api-version, e.g. ?api-version=2024-10-21 (or use the /openai/v1 route)", http.StatusBadRequest)
        return
    }
    http.Error(w, err.Error(), http.StatusBadRequest)
}

Prevention

When it happens

Trigger: Calling /azure/openai/deployments/gpt-4o/chat/completions with no query string — e.g. a client that assumes the proxy injects the version, or a URL from which the query was accidentally dropped.

Common situations: Assuming the v1-route convention (version optional) applies to the legacy route; URL templating that omits empty parameters; migrating configs where the version lived in a different field that went unset.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/fb7efcd57f210703. Report an issue: GitHub.