{"record":{"id":"d762e50a331bc2f6","repo":"infiniflow/ragflow","slug":"tenantmodel-id-model-id-is-disabled","errorCode":null,"errorMessage":"TenantModel id={model_id} is disabled.","messagePattern":"TenantModel id=(.+?) is disabled\\.","errorType":"exception","errorClass":"LookupError","httpStatus":null,"severity":"error","filePath":"api/db/joint_services/tenant_model_service.py","lineNumber":332,"sourceCode":"            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\n    ok, instance_obj = TenantModelInstanceService.get_by_id(model_obj.instance_id)\n    if not ok:","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/db/joint_services/tenant_model_service.py#L314-L350","documentation":"LookupError raised by get_model_config_by_id when the tenant_model row exists but its status equals ActiveStatusEnum.INACTIVE. The row was found by id, then explicitly rejected because the user (or admin) disabled it. This is a state error, not a missing-row error: the model must be re-enabled before it can serve the requested model_type.","triggerScenarios":"Calling get_model_config_by_id with a model id whose tenant_model.status == ActiveStatusEnum.INACTIVE — typically after the user toggled the model off in Model Providers, or an admin bulk-disabled it, while a dataset/assistant still references it.","commonSituations":"Disabling an API-key-exhausted or deprecated model and forgetting dependent datasets; team spaces where one member disables a shared model; after provider key rotation the model is parked inactive.","solutions":["Re-enable the model in System -> Model Providers (set status back to ACTIVE).","If it should stay disabled, switch dependent datasets/assistants to another model id.","Before disabling a model, audit references (tenant_embd_id / llm_id fields) and migrate them.","In API integrations, catch LookupError and surface a 'model disabled, choose another' message instead of retrying."],"exampleFix":"# before\nconfig = get_model_config_by_id(tenant_id, LLMType.CHAT, llm_id)\n\n# after\nexist, obj = TenantModelService.get_by_id(llm_id)\nif exist and obj.status == ActiveStatusEnum.INACTIVE.value:\n    raise RuntimeError(\"Chat model is disabled; enable it in Model Providers or pick another\")\nconfig = get_model_config_by_id(tenant_id, LLMType.CHAT, llm_id)","handlingStrategy":"try-catch","validationCode":"exist, obj = TenantModelService.get_by_id(model_id)\nif exist and obj.status == ActiveStatusEnum.INACTIVE.value:\n    raise RuntimeError(\"Model is disabled; enable it or choose another\")","typeGuard":"def model_usable(model_id: str) -> bool:\n    exist, obj = TenantModelService.get_by_id(model_id)\n    return exist and obj.status != ActiveStatusEnum.INACTIVE.value","tryCatchPattern":"try:\n    config = get_model_config_by_id(tenant_id, model_type, model_id)\nexcept LookupError as e:\n    if \"is disabled\" in str(e):\n        # prompt user to enable the model or pick another; not transient\n        ...","preventionTips":["Before disabling a model, list datasets/assistants referencing its id and migrate them.","Surface model status in selection UIs so disabled models cannot be chosen.","Never auto-retry: disabled state requires user action."],"tags":["model-status","tenant-model","ragflow","state"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}