{"record":{"id":"627035d8a97857db","repo":"zylon-ai/private-gpt","slug":"ocr-model-settings-docling-ocr-model-not-suppo","errorCode":null,"errorMessage":"OCR model {settings().docling.ocr_model} not supported","messagePattern":"OCR model (.+?) not supported","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/readers/docling/common.py","lineNumber":40,"sourceCode":"    \"\"\"Get the OCR languages.\n\n    Returns:\n        list[str]: List of OCR languages.\n    \"\"\"\n    langs: list[str] | None = settings().docling.langs\n    if not langs:\n        raise ValueError(\"No OCR languages specified.\")\n    match settings().docling.ocr_model:\n        case \"easyocr\":\n            langs = [convert_to_easyocr_lang(lang) for lang in langs]\n        case \"tesseract\":\n            langs = [convert_to_tesseract_lang(lang) for lang in langs]\n        case \"rapidocr\":\n            langs = [convert_to_rapidocr_lang(lang) for lang in langs]\n        case \"ocrmac\":\n            langs = [convert_to_ocrmac_lang(lang) for lang in langs]\n        case _:\n            raise ValueError(f\"OCR model {settings().docling.ocr_model} not supported\")\n    return langs\n\n\nasync def calculate_file_priority(\n    file_bytes: bytes, pages: int | None = None, **kwargs: Any\n) -> int:\n    \"\"\"Calculate processing priority based on file size and page count.\n\n    Priority levels:\n    - 0: High priority (small files < 1MB and <= 100 pages)\n    - 1: Low priority (files > 10MB or > 50 pages)\n    \"\"\"\n    file_size = len(file_bytes)\n\n    # High priority: files under 1MB\n    if file_size < 1_000_000 and (pages is None or pages <= 100):\n        return 0\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/readers/docling/common.py#L22-L58","documentation":"Raised by get_ocr_langs() when settings().docling.ocr_model is not one of the four supported OCR engines: easyocr, tesseract, rapidocr, ocrmac. The function then maps each language code to the engine-specific format via the LANG_TO_* dictionaries in utils.py, so an unknown engine has no mapping path. In stock builds the settings model already constrains ocr_model with a Literal type, so this branch is a defensive backstop that mainly fires when settings are injected or constructed without full validation.","triggerScenarios":"settings.docling.ocr_model set to anything other than 'easyocr', 'tesseract', 'rapidocr', or 'ocrmac' while OCR language conversion runs. Because DoclingSettings declares ocr_model: Literal[...], the typical trigger is a programmatically built/unvalidated DoclingConfig, a plugin-supplied settings object, or a settings loader that bypasses Literal validation.","commonSituations":"Typos in settings.yaml like 'tessaract' or 'easy-ocr' (usually caught earlier by pydantic Literal validation — if you see this error instead, your settings path skipped validation); upgrading private-gpt where the supported engine list changed; custom builds adding an engine name without registering a language map.","solutions":["Set ocr_model to one of the four supported values in settings.yaml: easyocr, tesseract, rapidocr, or ocrmac.","Check for typos in the docling.ocr_model key (e.g., 'tessaract', 'EasyOCR').","If you construct DoclingConfig in code, validate it (model_validate) so Literal constraints catch bad values at construction instead of at conversion time.","Pick ocrmac only on macOS (it wraps Apple's Vision framework); pick tesseract only if the server image has tesseract installed."],"exampleFix":"# settings.yaml — before\n# docling:\n#   ocr_model: easy-ocr\n\n# after\n# docling:\n#   ocr_model: easyocr","handlingStrategy":"validation","validationCode":"SUPPORTED_OCR = {\"easyocr\", \"tesseract\", \"rapidocr\", \"ocrmac\"}\n\ndef validate_ocr_engine(cfg) -> None:\n    if cfg.use_ocr and cfg.ocr_model not in SUPPORTED_OCR:\n        raise SystemExit(f\"docling.ocr_model must be one of {sorted(SUPPORTED_OCR)}\")\n\nvalidate_ocr_engine(settings().docling)","typeGuard":"def is_supported_ocr_model(model: str) -> bool:\n    return model in {\"easyocr\", \"tesseract\", \"rapidocr\", \"ocrmac\"}","tryCatchPattern":"try:\n    langs = get_ocr_langs()\nexcept ValueError as e:\n    if \"not supported\" in str(e) and \"OCR model\" in str(e):\n        raise ConfigurationError(str(e)) from e  # config bug: fail fast, no retry\n    raise","preventionTips":["Let pydantic validate settings: never construct DoclingConfig from raw dicts without model_validate.","Pick ocrmac only on macOS; tesseract only where the server image includes it."],"tags":["docling","ocr","configuration","enum"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}