alibaba/open-code-review · error
provider %q: %w
Error message
provider %q: %w
What it means
Wrapper error ("provider %q: %w") from tryProviderConfig when ValidateProtocol rejects the protocol that a preset provider declares internally. This comes from the preset's built-in Protocol after normalization, so hitting it usually means the installed preset table and the binary's validation rules disagree (version skew), not a user typo.
Source
Thrown at internal/llm/resolver.go:433
}
case apiKeyCmd == "" && isPreset && preset.EnvVar != "":
// Env var is the last resort: only when neither api_key nor api_key_cmd
// is set, and only for preset providers (custom ones have no fallback).
// Same whitespace rule as the static key above, so `export
// ANTHROPIC_API_KEY=" "` reports "no api_key configured" instead of
// sending `Authorization: Bearer ` and getting an opaque 401.
if v := os.Getenv(preset.EnvVar); strings.TrimSpace(v) != "" {
apiKey = v
}
}
var url, protocol, authHeader, model string
var extraBody map[string]any
if isPreset {
url = preset.BaseURL
protocol = NormalizeProtocol(preset.Protocol)
if err := ValidateProtocol(protocol); err != nil {
return ResolvedEndpoint{}, false, fmt.Errorf("provider %q: %w", cfg.Provider, err)
}
authHeader = preset.AuthHeader
if entry.URL != "" {
url = entry.URL
}
if entry.Protocol != "" {
normalized := NormalizeProtocol(entry.Protocol)
if err := ValidateProtocol(normalized); err != nil {
return ResolvedEndpoint{}, false, fmt.Errorf("provider %q: %w", cfg.Provider, err)
}
protocol = normalized
}
} else {
// Custom provider: protocol is always required; model can come from
// cfg.Model. url is required for every protocol that names an HTTP
// endpoint, which is all of them except bedrock — there the region
// decides the host, so demanding a url would mean storing a value the
// client never reads.View on GitHub (pinned to 5cf97d0d15)
Solutions
- Rebuild/reinstall ocr so the preset registry and validator come from the same version
- Override the protocol in the provider entry ("protocol": "anthropic" or "openai") to bypass the preset's default
- Report/fix the preset definition so its Protocol matches a value accepted by ValidateProtocol
Example fix
// before — providers.json preset: {"name":"acme","protocol":"acme-chat"}
// after — override in config.json
{
"provider": "acme",
"providers": { "acme": { "protocol": "openai", "url": "https://api.acme.dev/v1" } }
} Defensive patterns
Strategy: fallback
Try / catch
if err := resolve(); err != nil {
if strings.Contains(err.Error(), "provider \"my-provider\": ") && strings.Contains(err.Error(), "protocol") {
log.Println("preset protocol invalid; setting explicit protocol in entry")
// retry with "protocol": "openai" in the provider entry
}
return err
} Prevention
- Keep the ocr binary and its preset data from the same build/version
- Set an explicit "protocol" in provider entries when you depend on a specific wire format
- Report preset/validator mismatches upstream instead of patching preset tables
When it happens
Trigger: Resolving a preset provider (LookupProvider hit); the preset's Protocol field normalizes to a value ValidateProtocol rejects. The user's config only triggers this by referencing the preset provider.
Common situations: Running a binary built against a newer/older preset registry than the validation code expects, or a locally patched/extended preset list with a hand-written protocol string.
Related errors
- OCR environment: %w
- provider %q is set but not configured in %s section
- custom provider %q requires a protocol field
- custom provider %q: %w
- custom provider %q not found
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/f151aa56e62e6d5d.
Report an issue: GitHub.