alibaba/open-code-review · error

custom provider %q requires a url field for protocol %q

Error message

custom provider %q requires a url field for protocol %q

What it means

The resolver builds an endpoint for a custom (non-preset) provider entry. Every protocol except anthropic-bedrock names a concrete HTTP endpoint, so a custom provider entry must carry a `url` field; bedrock is exempt because the AWS region determines the host. This error means a custom provider entry declared a valid, non-bedrock protocol but left `url` empty.

Source

Thrown at internal/llm/resolver.go:460

				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.
		if entry.Protocol == "" {
			return ResolvedEndpoint{}, false, fmt.Errorf("custom provider %q requires a protocol field", cfg.Provider)
		}
		normalized := NormalizeProtocol(entry.Protocol)
		if err := ValidateProtocol(normalized); err != nil {
			return ResolvedEndpoint{}, false, fmt.Errorf("custom provider %q: %w", cfg.Provider, err)
		}
		if normalized != ProtocolAnthropicBedrock && entry.URL == "" {
			return ResolvedEndpoint{}, false, fmt.Errorf("custom provider %q requires a url field for protocol %q", cfg.Provider, normalized)
		}
		url = entry.URL
		protocol = normalized
	}

	// Ambient auth follows the protocol actually in force, which is why this is
	// resolved after the override above rather than read off the preset. A preset
	// declares ambient auth (AmbientAuth), but an entry may override the preset's
	// protocol: a bedrock preset switched to "openai" speaks a protocol with no
	// SigV4 signing and needs a token like anything else. Conversely an entry
	// that selects the bedrock protocol explicitly signs its requests whatever
	// the preset says.
	ambientAuth := protocol == ProtocolAnthropicBedrock ||
		(isPreset && preset.AmbientAuth && entry.Protocol == "")

	// No credential at all is an error, and it is reported before api_key_cmd
	// runs: only the command's *execution* is deferred, not the emptiness check.
	// An ambient-auth provider is the exception — it has no key to configure,

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Add a `url` field to the provider entry, e.g. url = "https://api.example.com/v1"
  2. If the provider really is AWS Bedrock, set protocol = "anthropic-bedrock" (url is then not required; configure region instead)
  3. Check the key spelling in the config — the url must be inside the same provider entry block

Example fix

// before (config.toml)
[providers.my-llm]
protocol = "openai"
model = "llama3"

// after
[providers.my-llm]
protocol = "openai"
url = "http://localhost:8000/v1"
model = "llama3"
Defensive patterns

Strategy: validation

Validate before calling

// Go: check a custom provider entry before resolution
func validateCustomProvider(name, protocol, url string) error {
	if protocol == "" {
		return fmt.Errorf("provider %q: missing protocol", name)
	}
	if strings.EqualFold(protocol, "anthropic-bedrock") {
		return nil // url not required for bedrock
	}
	if url == "" {
		return fmt.Errorf("provider %q: protocol %q requires url", name, protocol)
	}
	return nil
}

Type guard

func hasURLForProtocol(protocol, url string) bool {
	return url != "" || strings.EqualFold(protocol, "anthropic-bedrock")
}

Try / catch

ep, ok, err := resolver.TryProviderConfig(cfg, override)
if err != nil {
	if strings.Contains(err.Error(), "requires a url field") {
		fmt.Fprintf(os.Stderr, "config error: add url for provider: %v\n", err)
		os.Exit(2)
	}
	return err
}

Prevention

When it happens

Trigger: A [providers] entry without a preset (custom provider) sets `protocol` (e.g. "openai" or "anthropic") but omits `url`, and `ocr review` (via tryOCRConfig -> tryProviderConfig) resolves the endpoint.

Common situations: Adding a new custom/self-hosted provider (vLLM, Ollama, OpenRouter) and forgetting the url; copying an existing bedrock entry (which legitimately has no url) and changing only the protocol; typo-ing the url key so the entry field parses as empty.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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