{"record":{"id":"7dec4a4813d280e3","repo":"infiniflow/ragflow","slug":"ocr-model-name-is-required-7dec4a","errorCode":null,"errorMessage":"OCR model name is required","messagePattern":"OCR model name is required","errorType":"exception","errorClass":"LookupError","httpStatus":null,"severity":"warning","filePath":"api/db/services/tenant_llm_service.py","lineNumber":150,"sourceCode":"        e, tenant = TenantService.get_by_id(tenant_id)\n        if not e:\n            raise LookupError(\"Tenant not found\")\n\n        if llm_type == LLMType.EMBEDDING.value:\n            mdlnm = tenant.embd_id if not llm_name else llm_name\n        elif llm_type == LLMType.ASR.value:\n            mdlnm = tenant.asr_id if not llm_name else llm_name\n        elif llm_type == LLMType.VISION.value:\n            mdlnm = tenant.img2txt_id if not llm_name else llm_name\n        elif llm_type == LLMType.CHAT.value:\n            mdlnm = tenant.llm_id if not llm_name else llm_name\n        elif llm_type == LLMType.RERANK:\n            mdlnm = tenant.rerank_id if not llm_name else llm_name\n        elif llm_type == LLMType.TTS:\n            mdlnm = tenant.tts_id if not llm_name else llm_name\n        elif llm_type == LLMType.OCR:\n            if not llm_name:\n                raise LookupError(\"OCR model name is required\")\n            mdlnm = llm_name\n        else:\n            assert False, \"LLM type error\"\n\n        model_config = cls.get_api_key(tenant_id, mdlnm, llm_type)\n        mdlnm, fid = TenantLLMService.split_model_name_and_factory(mdlnm)\n        if not model_config:  # for some cases seems fid mismatch\n            model_config = cls.get_api_key(tenant_id, mdlnm, llm_type)\n        if model_config:\n            model_config = model_config.to_dict()\n            api_key, is_tools, api_key_payload = cls._decode_api_key_config(model_config.get(\"api_key\", \"\"))\n            model_config[\"api_key\"] = api_key\n            if api_key_payload is not None:\n                model_config[\"api_key_payload\"] = api_key_payload\n            if is_tools is not None:\n                model_config[\"is_tools\"] = is_tools\n        elif llm_type == LLMType.EMBEDDING and fid == \"Builtin\" and \"tei-\" in os.getenv(\"COMPOSE_PROFILES\", \"\") and mdlnm == os.getenv(\"TEI_MODEL\", \"\"):\n            embedding_cfg = settings.EMBEDDING_CFG","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/db/services/tenant_llm_service.py#L132-L168","documentation":"Raised by TenantLLMService.get_model_config when llm_type is OCR and no llm_name was supplied. Unlike other types, OCR has no tenant-level default id, so the model name must come from the caller; a missing name is an input error.","triggerScenarios":"Invoking OCR model resolution (e.g. deepdoc OCR model config APIs) with llm_type='ocr' and llm_name=None or empty.","commonSituations":"Client code copying the chat/embedding pattern (which falls back to tenant defaults) for OCR; UI flows that forget to carry the selected OCR model name; version changes where OCR became explicitly named.","solutions":["Always pass a concrete llm_name when requesting OCR model configuration.","Validate llm_name is a non-empty string before calling get_model_config.","Surface a form error in the UI when no OCR model is selected instead of calling the API."],"exampleFix":"# before\ncfg = TenantLLMService.get_model_config(tenant_id, LLMType.OCR)  # raises\n\n# after\nif not llm_name:\n    raise ValueError('OCR model name is required')\ncfg = TenantLLMService.get_model_config(tenant_id, LLMType.OCR, llm_name)","handlingStrategy":"type-guard","validationCode":"if llm_type == LLMType.OCR and not (llm_name and llm_name.strip()):\n    return json_error_response('OCR model name is required', 400)","typeGuard":"def has_required_model_name(llm_type: str, llm_name: str | None) -> bool:\n    if llm_type == LLMType.OCR:\n        return isinstance(llm_name, str) and bool(llm_name.strip())\n    return True","tryCatchPattern":"try:\n    cfg = TenantLLMService.get_model_config(tenant_id, LLMType.OCR, llm_name)\nexcept LookupError as e:\n    if 'OCR model name' in str(e):\n        return json_error_response('select an OCR model first', 400)\n    raise","preventionTips":["OCR has no tenant default: always require an explicit model selection in UI/client.","Validate required parameters per llm_type before calling model-config APIs."],"tags":["validation","ocr","model-config","missing-parameter"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}