infiniflow/ragflow · warning · LookupError

OCR model name is required

Error message

OCR model name is required

What it means

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.

Source

Thrown at api/db/services/tenant_llm_service.py:150

        e, tenant = TenantService.get_by_id(tenant_id)
        if not e:
            raise LookupError("Tenant not found")

        if llm_type == LLMType.EMBEDDING.value:
            mdlnm = tenant.embd_id if not llm_name else llm_name
        elif llm_type == LLMType.ASR.value:
            mdlnm = tenant.asr_id if not llm_name else llm_name
        elif llm_type == LLMType.VISION.value:
            mdlnm = tenant.img2txt_id if not llm_name else llm_name
        elif llm_type == LLMType.CHAT.value:
            mdlnm = tenant.llm_id if not llm_name else llm_name
        elif llm_type == LLMType.RERANK:
            mdlnm = tenant.rerank_id if not llm_name else llm_name
        elif llm_type == LLMType.TTS:
            mdlnm = tenant.tts_id if not llm_name else llm_name
        elif llm_type == LLMType.OCR:
            if not llm_name:
                raise LookupError("OCR model name is required")
            mdlnm = llm_name
        else:
            assert False, "LLM type error"

        model_config = cls.get_api_key(tenant_id, mdlnm, llm_type)
        mdlnm, fid = TenantLLMService.split_model_name_and_factory(mdlnm)
        if not model_config:  # for some cases seems fid mismatch
            model_config = cls.get_api_key(tenant_id, mdlnm, llm_type)
        if model_config:
            model_config = model_config.to_dict()
            api_key, is_tools, api_key_payload = cls._decode_api_key_config(model_config.get("api_key", ""))
            model_config["api_key"] = api_key
            if api_key_payload is not None:
                model_config["api_key_payload"] = api_key_payload
            if is_tools is not None:
                model_config["is_tools"] = is_tools
        elif llm_type == LLMType.EMBEDDING and fid == "Builtin" and "tei-" in os.getenv("COMPOSE_PROFILES", "") and mdlnm == os.getenv("TEI_MODEL", ""):
            embedding_cfg = settings.EMBEDDING_CFG

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Always pass a concrete llm_name when requesting OCR model configuration.
  2. Validate llm_name is a non-empty string before calling get_model_config.
  3. Surface a form error in the UI when no OCR model is selected instead of calling the API.

Example fix

# before
cfg = TenantLLMService.get_model_config(tenant_id, LLMType.OCR)  # raises

# after
if not llm_name:
    raise ValueError('OCR model name is required')
cfg = TenantLLMService.get_model_config(tenant_id, LLMType.OCR, llm_name)
Defensive patterns

Strategy: type-guard

Validate before calling

if llm_type == LLMType.OCR and not (llm_name and llm_name.strip()):
    return json_error_response('OCR model name is required', 400)

Type guard

def has_required_model_name(llm_type: str, llm_name: str | None) -> bool:
    if llm_type == LLMType.OCR:
        return isinstance(llm_name, str) and bool(llm_name.strip())
    return True

Try / catch

try:
    cfg = TenantLLMService.get_model_config(tenant_id, LLMType.OCR, llm_name)
except LookupError as e:
    if 'OCR model name' in str(e):
        return json_error_response('select an OCR model first', 400)
    raise

Prevention

When it happens

Trigger: Invoking OCR model resolution (e.g. deepdoc OCR model config APIs) with llm_type='ocr' and llm_name=None or empty.

Common situations: 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.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/7dec4a4813d280e3. Report an issue: GitHub.