alibaba/open-code-review · error
invalid extra header %q: expected key=value
Error message
invalid extra header %q: expected key=value
What it means
Extra headers are configured as a list of "key=value" strings. During resolution, each entry is split on the first '='; an entry without a '=' separator fails with 'invalid extra header %q: expected key=value'. This gives an early, clear error instead of a silently dropped or mangled header at request time.
Source
Thrown at internal/llm/resolver.go:869
func ParseExtraHeaders(raw string) (map[string]string, error) {
if raw == "" {
return nil, nil
}
pairs, err := splitHeaderPairs(raw)
if err != nil {
return nil, err
}
result := make(map[string]string)
for _, pair := range pairs {
pair = strings.TrimSpace(pair)
if pair == "" {
continue
}
parts := strings.SplitN(pair, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid extra header %q: expected key=value", pair)
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
if key == "" {
return nil, fmt.Errorf("invalid extra header %q: empty header name", pair)
}
if reservedHeaders[strings.ToLower(key)] {
return nil, fmt.Errorf("extra header %q conflicts with a reserved header; use the dedicated config field instead", key)
}
if len(value) >= 2 && value[0] == '"' && value[len(value)-1] == '"' {
value = value[1 : len(value)-1]
}
result[key] = value
}
return result, nil
}
// splitHeaderPairs splits a comma-separated string while respecting double-quoted segments.View on GitHub (pinned to 5cf97d0d15)
Solutions
- Rewrite the entry as key=value, e.g. extra_headers = ["X-Custom-Trace=abc123"]
- If the header needs no value, use an empty value explicitly: "X-Custom-Trace="
- Check the separator: HTTP colon syntax ("Key: value") is not accepted here — only '='
- Trim stray whitespace/quotes so the entry isn't split unexpectedly
Example fix
// before (config file) extra_headers = ["X-Custom-Trace"] // after extra_headers = ["X-Custom-Trace=abc123"]
Defensive patterns
Strategy: validation
Validate before calling
// validate extra_headers entries before running ocr
for _, h := range cfg.ExtraHeaders {
if !strings.Contains(h, "=") {
return fmt.Errorf("extra header %q must be key=value", h)
}
if strings.TrimSpace(strings.SplitN(h, "=", 2)[0]) == "" {
return fmt.Errorf("extra header %q has empty key", h)
}
} Try / catch
if _, _, err := llm.ResolveEndpoint(cfg, ""); err != nil {
var ehErr = "invalid extra header"
if strings.Contains(err.Error(), ehErr) {
// print the offending entry quoted in the error and fix the config
}
} Prevention
- Always author entries as key=value, even when the value is empty ("Key=")
- Use '=' not ':' — HTTP header syntax is not accepted in config
- Reserve auth/content-type style headers for dedicated fields; extras are for custom metadata
When it happens
Trigger: An extra_headers list entry with no '=' character, e.g. extra_headers = ["X-Custom-Trace"] or an empty-ish token after trimming, passed through resolver validation.
Common situations: Adding a bare header name intending to set it later; YAML/TOML list item quoting mistakes that split 'Key: value' into the wrong field; copy-pasting an HTTP header line using ':' instead of '='.
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
- header name must not be empty
- header value for %q must not be empty
- invalid auth_header: %w
- unsupported auth_header value %q; expected "x-api-key" or "a
- 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/5c5b52d5fc27a76f.
Report an issue: GitHub.