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

  1. Change auth_header to exactly "x-api-key" or "authorization" ("bearer" is accepted as an alias for authorization); casing is ignored
  2. Remove the auth_header key entirely to use the protocol default
  3. 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

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


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/4444a35bb311b6c1. Report an issue: GitHub.