unclecode/crawl4ai · error · LLMProviderNotAllowed
LLM provider not allowed
Error message
LLM provider not allowed
What it means
resolve_llm in deploy/docker/llm_broker.py raises LLMProviderNotAllowed when the requested provider's family (per _family) is not in allowed_provider_families(config) — the allowlist derived from server config (providers with configured keys plus explicit allow rules). Credentials are server-derived only; a request may pick a provider name but never a base_url/token, so an unapproved provider is rejected outright.
Source
Thrown at deploy/docker/llm_broker.py:57
fams.add(_family(cfg["provider"]))
return {f for f in fams if f}
def resolve_llm(config: Dict, requested_provider: Optional[str] = None) -> Dict:
"""Resolve the LLM call parameters fully server-side.
A request-supplied base_url/api_token is intentionally NOT a parameter here:
callers pass only the provider *name*. Returns {provider, base_url,
api_token, temperature}, all server-derived.
"""
from utils import get_llm_api_key, get_llm_base_url, get_llm_temperature
default = config["llm"]["provider"]
provider = requested_provider or default
fams = allowed_provider_families(config)
if fams and _family(provider) not in fams:
raise LLMProviderNotAllowed("LLM provider not allowed")
return {
"provider": provider,
"base_url": get_llm_base_url(config, provider), # canonical, never from request
"api_token": get_llm_api_key(config, provider), # server credential
"temperature": get_llm_temperature(config, provider),
}
View on GitHub (pinned to 7e80152142)
Solutions
- Check the deployment's LLM config for which providers have API keys/allow entries — allowed_provider_families() is the source of truth.
- Request one of the allowed providers, or omit provider to use the configured default.
- Operators: add the provider's API key / allow entry in config so its family joins the allowlist.
- Catch LLMProviderNotAllowed client-side and surface an 'upgrade/choose provider' message rather than retrying.
Example fix
# before
POST /llm/job {"provider": "gemini", ...} # deployment allows anthropic only
# after
POST /llm/job {"provider": "anthropic", ...} # or omit provider for the server default Defensive patterns
Strategy: type-guard
Validate before calling
from llm_broker import allowed_provider_families, _family
def provider_allowed(config: dict, provider: str | None) -> bool:
fams = allowed_provider_families(config)
return not fams or _family(provider or config["llm"]["provider"]) in fams Type guard
def is_allowed_provider(config, requested) -> bool:
fams = allowed_provider_families(config)
return requested is None or (not fams or _family(requested) in fams) Try / catch
from llm_broker import LLMProviderNotAllowed
try:
creds = resolve_llm(config, requested_provider)
except LLMProviderNotAllowed:
creds = resolve_llm(config, None) # fall back to server default provider Prevention
- Expose the allowed provider list via a config/status endpoint and drive UI dropdowns from it.
- Omit provider to get the always-allowed default.
- Never send base_url/api_token from clients — the server derives credentials.
When it happens
Trigger: POSTing an extraction job with provider='openai' when the deployment only configures/permits anthropic-family providers; provider='azure-openai' vs 'openai' family mismatch; omitting provider is safe (falls back to config['llm']['provider'], always allowed).
Common situations: Multi-tenant deployments restricting tenants to one vendor; a provider key not set in the server env/config so its family never lands in the allowlist; renaming or adding a provider in config without updating clients.
Related errors
- [NSTProxy] API Error: {data.get('msg', 'Unknown error')}
- [NSTProxy] Invalid API response — expected a non-empty list
- CrawlerRunConfig must be provided
- Invalid source(s): {invalid}. Valid: {VALID_SOURCES}
- Setting '{name}' is deprecated. {self._UNWANTED_PROPS[name]}
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/0a99a6cc1c5b58d4.
Report an issue: GitHub.