{"record":{"id":"76d695e45803f744","repo":"infiniflow/ragflow","slug":"tenantmodel-id-model-id-not-found","errorCode":null,"errorMessage":"TenantModel id={model_id} not found.","messagePattern":"TenantModel id=(.+?) not found\\.","errorType":"exception","errorClass":"LookupError","httpStatus":null,"severity":"error","filePath":"api/db/joint_services/tenant_model_service.py","lineNumber":330,"sourceCode":"            # SoMark/OCR factories read parser config (somark_*, parse_method, ...)\n            # from model_config[\"extra\"]; see tenant_llm_service.LLMBundle OCR path.\n            model_config[\"extra\"] = model_extra\n\n        if api_key_payload is not None:\n            model_config[\"api_key_payload\"] = api_key_payload\n\n        return model_config\n    else:\n        raise LookupError(f\"Model {model_name} not found for model {model_type_val}\")\n\n\ndef get_model_config_by_id(tenant_id: str, model_type: str | enum.Enum, model_id: str):\n    \"\"\"Get model config from tenant_model by its id (CharField PK).\"\"\"\n    model_type_val = model_type if isinstance(model_type, str) else model_type.value\n    model_type_bin = calculate_model_type(model_type_val)\n    exist, model_obj = TenantModelService.get_by_id(model_id)\n    if not exist:\n        raise LookupError(f\"TenantModel id={model_id} not found.\")\n    if model_obj.status == ActiveStatusEnum.INACTIVE.value:\n        raise LookupError(f\"TenantModel id={model_id} is disabled.\")\n    if model_obj.status == ActiveStatusEnum.UNSUPPORTED.value:\n        raise LookupError(f\"TenantModel id={model_id} cannot be used as {model_type_val} model.\")\n    if not (model_obj.model_type & model_type_bin):\n        raise LookupError(f\"TenantModel id={model_id} cannot be used as {model_type_val} model.\")\n\n    ok, provider_obj = TenantModelProviderService.get_by_id(model_obj.provider_id)\n    if not ok:\n        raise LookupError(f\"Provider id={model_obj.provider_id} not found for model id={model_id}.\")\n\n    # Validate that tenant_id owns the provider or is a joined tenant of the provider's owner.\n    if tenant_id != provider_obj.tenant_id:\n        joined_tenants = TenantService.get_joined_tenants_by_user_id(tenant_id)\n        joined_tenant_ids = [t[\"tenant_id\"] for t in joined_tenants]\n        if provider_obj.tenant_id not in joined_tenant_ids:\n            raise LookupError(f\"Tenant {tenant_id} has no access to provider owned by tenant {provider_obj.tenant_id}.\")\n","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/db/joint_services/tenant_model_service.py#L312-L348","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconfig = TenantModelService.get_model_config_by_id(tenant_id, LLMType.EMBEDDING, dataset.embd_id)\n\n// after\nexist, _ = TenantModelService.get_by_id(dataset.embd_id)\nif not exist:\n    raise ValueError(f\"Embedding model {dataset.embd_id} no longer exists; re-select it on the dataset\")\nconfig = TenantModelService.get_model_config_by_id(tenant_id, LLMType.EMBEDDING, dataset.embd_id)","handlingStrategy":"validation","validationCode":"exist, model_obj = TenantModelService.get_by_id(model_id)\nif not exist:\n    raise ValueError(f\"Model {model_id} does not exist; re-select it in Model Providers\")","typeGuard":"def model_id_exists(model_id: str) -> bool:\n    exist, _ = TenantModelService.get_by_id(model_id)\n    return exist","tryCatchPattern":"try:\n    config = get_model_config_by_id(tenant_id, model_type, model_id)\nexcept LookupError as e:\n    # treat as permanent config error: surface to user, do not retry\n    raise HTTPException(404, str(e))","preventionTips":["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."],"tags":["lookup","tenant-model","ragflow","database"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}