infiniflow/ragflow · error · LookupError
TenantModel id={model_id} not found.
Error message
TenantModel id={model_id} not found. What it means
LookupError raised by TenantModelService.get_model_config_by_id when TenantModelService.get_by_id(model_id) returns exist=False. The function resolves a tenant_model row by its CharField primary key before checking status, model_type bits, and provider ownership; a missing row fails at the first gate. It signals the model id stored on the caller's entity (chat assistant, canvas, dataset embedding setting) does not exist in the tenant_model table.
Source
Thrown at api/db/joint_services/tenant_model_service.py:330
# SoMark/OCR factories read parser config (somark_*, parse_method, ...)
# from model_config["extra"]; see tenant_llm_service.LLMBundle OCR path.
model_config["extra"] = model_extra
if api_key_payload is not None:
model_config["api_key_payload"] = api_key_payload
return model_config
else:
raise LookupError(f"Model {model_name} not found for model {model_type_val}")
def get_model_config_by_id(tenant_id: str, model_type: str | enum.Enum, model_id: str):
"""Get model config from tenant_model by its id (CharField PK)."""
model_type_val = model_type if isinstance(model_type, str) else model_type.value
model_type_bin = calculate_model_type(model_type_val)
exist, model_obj = TenantModelService.get_by_id(model_id)
if not exist:
raise LookupError(f"TenantModel id={model_id} not found.")
if model_obj.status == ActiveStatusEnum.INACTIVE.value:
raise LookupError(f"TenantModel id={model_id} is disabled.")
if model_obj.status == ActiveStatusEnum.UNSUPPORTED.value:
raise LookupError(f"TenantModel id={model_id} cannot be used as {model_type_val} model.")
if not (model_obj.model_type & model_type_bin):
raise LookupError(f"TenantModel id={model_id} cannot be used as {model_type_val} model.")
ok, provider_obj = TenantModelProviderService.get_by_id(model_obj.provider_id)
if not ok:
raise LookupError(f"Provider id={model_obj.provider_id} not found for model id={model_id}.")
# Validate that tenant_id owns the provider or is a joined tenant of the provider's owner.
if tenant_id != provider_obj.tenant_id:
joined_tenants = TenantService.get_joined_tenants_by_user_id(tenant_id)
joined_tenant_ids = [t["tenant_id"] for t in joined_tenants]
if provider_obj.tenant_id not in joined_tenant_ids:
raise LookupError(f"Tenant {tenant_id} has no access to provider owned by tenant {provider_obj.tenant_id}.")
View on GitHub (pinned to 554fb1133a)
Solutions
- Look up the model id in the Model Providers page (or SELECT * FROM tenant_model WHERE id=...) to confirm the row exists in the current database.
- If the row is gone, re-select the model on the consuming entity (dataset embedding model, assistant LLM) so a fresh tenant_model id is persisted.
- If deleting models, first repoint or delete dependent datasets/assistants to avoid dangling references.
- Guard call sites with get_model_type_by_id / existence checks before invoking config resolution.
Example fix
// before
config = TenantModelService.get_model_config_by_id(tenant_id, LLMType.EMBEDDING, dataset.embd_id)
// after
exist, _ = TenantModelService.get_by_id(dataset.embd_id)
if not exist:
raise ValueError(f"Embedding model {dataset.embd_id} no longer exists; re-select it on the dataset")
config = TenantModelService.get_model_config_by_id(tenant_id, LLMType.EMBEDDING, dataset.embd_id) Defensive patterns
Strategy: validation
Validate before calling
exist, model_obj = TenantModelService.get_by_id(model_id)
if not exist:
raise ValueError(f"Model {model_id} does not exist; re-select it in Model Providers") Type guard
def model_id_exists(model_id: str) -> bool:
exist, _ = TenantModelService.get_by_id(model_id)
return exist Try / catch
try:
config = get_model_config_by_id(tenant_id, model_type, model_id)
except LookupError as e:
# treat as permanent config error: surface to user, do not retry
raise HTTPException(404, str(e)) Prevention
- Cascade-delete or repoint dependent datasets/assistants when removing a model.
- Store tenant_model ids, not free-text names, in entity config fields.
- Run a periodic orphan check joining entity model-id columns to tenant_model.
When it happens
Trigger: Calling get_model_config_by_id(tenant_id, model_type, model_id) with a stale, deleted, or malformed model id — e.g. the tenant_model row was deleted after being referenced by a chat/dataset, or a UUID from another environment was passed, or the id was truncated when copied.
Common situations: Model removed in System/Model Providers while still referenced by a dataset or assistant; DB restored/imported without tenant_model rows; multi-environment config where an id from one DB is used against another.
Related errors
- TenantModel id={model_id} is disabled.
- TenantModel id={model_id} cannot be used as {model_type_val}
- Model {model_name} not found for type {model_type_val}.
- Provider id={model_obj.provider_id} not found for model {mod
- Model {model_name} not found.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/76d695e45803f744.
Report an issue: GitHub.