alibaba/open-code-review · error
unsupported auth_header value %q; expected "x-api-key" or "a
Error message
unsupported auth_header value %q; expected "x-api-key" or "authorization"
What it means
NormalizeAuthHeader validates the llm.auth_header field (used when protocol is anthropic). Only "x-api-key", "authorization", and the alias "bearer" are accepted, compared case-insensitively; anything else returns this error, later wrapped as 'OCR config file: unsupported auth_header value ...'.
Source
Thrown at internal/llm/resolver.go:833
}
}
return false
}
// NormalizeAuthHeader normalizes an auth header value to a canonical form.
// It returns an error for unrecognized values.
func NormalizeAuthHeader(header string) (string, error) {
header = strings.TrimSpace(header)
if header == "" {
return "", nil
}
switch strings.ToLower(header) {
case "x-api-key":
return "x-api-key", nil
case "authorization", "bearer":
return "authorization", nil
default:
return "", fmt.Errorf("unsupported auth_header value %q; expected \"x-api-key\" or \"authorization\"", header)
}
}
// reservedHeaders are HTTP headers that extra_headers must not override.
// They are managed by dedicated config fields (auth_header, auth_token) or set automatically by the SDK.
// Letting extra_headers clobber them would cause confusing auth/content-type failures with no clear error.
var reservedHeaders = map[string]bool{
"authorization": true,
"x-api-key": true,
"content-type": true,
"user-agent": true,
}
// ParseExtraHeaders parses a string of comma-separated key=value pairs into a dictionary.
// Values may be double-quoted to include commas, e.g. X-Forwarded-For="1.2.3.4,5.6.7.8".
// Reserved header names (authorization, x-api-key, content-type, user-agent) are rejected
// to prevent accidental override of auth or content-type set by the SDK.
func ParseExtraHeaders(raw string) (map[string]string, error) {View on GitHub (pinned to 5cf97d0d15)
Solutions
- Change auth_header to exactly "x-api-key" or "authorization" ("bearer" is accepted as an alias for authorization); casing is ignored
- Remove the auth_header key entirely to use the protocol default
- If you need a non-standard auth header for a gateway, pass it via extra_headers instead — but note auth-related reserved headers are protected
Example fix
// before (config file) auth_header = "x_api_key" // after auth_header = "x-api-key"
Defensive patterns
Strategy: validation
Validate before calling
allowed := map[string]bool{"x-api-key": true, "authorization": true, "bearer": true}
if h := strings.TrimSpace(cfg.Llm.AuthHeader); h != "" && !allowed[strings.ToLower(h)] {
return fmt.Errorf("auth_header must be x-api-key or authorization, got %q", h)
} Try / catch
if _, _, err := llm.ResolveEndpoint(cfg, ""); err != nil {
if strings.Contains(err.Error(), "unsupported auth_header") {
// edit auth_header in the config to a supported value
}
} Prevention
- Only use x-api-key or authorization (bearer alias); casing does not matter
- Omit auth_header to inherit the protocol default
- Put gateway-specific headers in extra_headers, not auth_header
When it happens
Trigger: A completed [llm] block with protocol = anthropic and auth_header set to a value other than x-api-key/authorization/bearer, e.g. auth_header = "x-goog-api-key" or "Api-Key".
Common situations: Copying an auth header name from another provider's SDK into the config; misspelling the header ("x_api_key", "auth-header"); leaving a custom gateway header name in place after switching protocols.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- invalid auth_header: %w
- header name must not be empty
- header value for %q must not be empty
- invalid extra header %q: expected key=value
- invalid max_tokens %q: must be a positive integer
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/4444a35bb311b6c1.
Report an issue: GitHub.