infiniflow/ragflow · error · LookupError
Provider name is required to resolve model id for {model_nam
Error message
Provider name is required to resolve model id for {model_name}. What it means
LookupError raised in the model-name-to-id resolver (split_model_name path) when the 'model[@instance]@provider' string carries no provider segment. Except for the builtin TEI embedding escape hatch (COMPOSE_PROFILES contains 'tei-', name equals TEI_MODEL, provider 'Builtin' or empty), a provider name is mandatory to locate the tenant_model_provider row and then the model row. The error means the name string was a bare model name with no '@provider' suffix.
Source
Thrown at api/db/joint_services/tenant_model_service.py:390
return model_config
def resolve_model_id(tenant_id: str, model_type: str | enum.Enum, model_name: str) -> str | None:
"""Given a tenant_id, model_type and model_name (e.g. 'model@instance@provider'),
look up the corresponding tenant_model.id. Returns None if not found."""
pure_model_name, instance_name, provider_name = split_model_name(model_name)
model_type_val = model_type if isinstance(model_type, str) else model_type.value
# Builtin TEI embedding — no tenant_model row exists
compose_profiles = os.getenv("COMPOSE_PROFILES", "")
is_tei_builtin_embedding = (
model_type_val == LLMType.EMBEDDING.value and "tei-" in compose_profiles and pure_model_name == os.getenv("TEI_MODEL", "") and (provider_name == "Builtin" or not provider_name)
)
if is_tei_builtin_embedding:
return None
if not provider_name:
raise LookupError(f"Provider name is required to resolve model id for {model_name}.")
provider_obj = TenantModelProviderService.get_by_tenant_id_and_provider_name(tenant_id, provider_name)
if not provider_obj:
raise LookupError(f"Provider {provider_name} not found for model {model_name}.")
instance_obj = _resolve_instance_for_model(provider_obj, instance_name, model_name)
model_obj = TenantModelService.get_by_provider_id_and_instance_id_and_model_type_and_model_name(provider_obj.id, instance_obj.id, model_type_val, pure_model_name)
if not model_obj:
raise LookupError(f"Model {model_name} not found for type {model_type_val}.")
return model_obj.id
# Mapping from model-name field → (LLMType, tenant_model id field)
_MODEL_NAME_TO_ID_FIELD_MAP: dict[str, tuple[str, str]] = {
"llm_id": (LLMType.CHAT, "tenant_llm_id"),
"embd_id": (LLMType.EMBEDDING, "tenant_embd_id"),
"rerank_id": (LLMType.RERANK, "tenant_rerank_id"),
"asr_id": (LLMType.ASR, "tenant_asr_id"),View on GitHub (pinned to 554fb1133a)
Solutions
- Format the model reference as model@provider (or model@instance@provider), e.g. 'gpt-4o@OpenAI'.
- For builtin TEI embedding, verify COMPOSE_PROFILES includes the tei- profile and TEI_MODEL matches the name, or just use the 'Builtin' provider suffix.
- Normalize stored model names on write so the provider suffix is always present.
- Check split_model_name output for your string to see which segment is empty.
Example fix
# before model_id = get_model_id_from_name(tenant_id, LLMType.CHAT, "deepseek-chat") # after model_id = get_model_id_from_name(tenant_id, LLMType.CHAT, "deepseek-chat@DeepSeek")
Defensive patterns
Strategy: validation
Validate before calling
_, _, provider = split_model_name(model_name)
if not provider:
raise ValueError(f"'{model_name}' lacks a provider: use 'model@Provider'") Type guard
def has_provider_suffix(model_name: str) -> bool:
return bool(split_model_name(model_name)[2]) Try / catch
try:
model_id = get_model_id_from_name(tenant_id, model_type, model_name)
except LookupError as e:
if "Provider name is required" in str(e):
model_name = f"{model_name}@{default_provider}"
model_id = get_model_id_from_name(tenant_id, model_type, model_name) Prevention
- Always store model references as 'model[@instance]@provider'.
- For TEI builtin embedding, keep COMPOSE_PROFILES and TEI_MODEL consistent with stored names.
- Centralize model-string formatting in one helper instead of string concatenation at call sites.
When it happens
Trigger: Calling the resolver (e.g. via get_model_id_from_name used by id-param backfill) with names like 'gpt-4o' instead of 'gpt-4o@OpenAI'; an empty/null provider segment after split_model_name; TEI builtin conditions not all met (e.g. TEI_MODEL env unset) so the escape hatch is skipped.
Common situations: Hand-written DSL or API payloads storing bare model names; configs migrated from an older scheme where the provider suffix was optional; TEI deployment where COMPOSE_PROFILES or TEI_MODEL drifted so the builtin branch no longer matches.
Related errors
- Provider name is required.
- Model {model_name} not found for type {model_type_val}.
- Model {model_name} not found.
- main() returned a non-JSON-serializable value.
- WhatsApp session is not running.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/4d7f7cbf7439bddc.
Report an issue: GitHub.