docling-project/docling · error · ValueError

Invalid RapidOCR model spec {value!r}: {err}

Error message

Invalid RapidOCR model spec {value!r}: {err}

What it means

The final validation step routes the (backend, lang) pair through _resolve_rapidocr, which checks that the language is actually resolvable for that backend. If resolution raises ValueError, it is re-raised wrapped as "Invalid RapidOCR model spec {value!r}: {err}" so the original cause (usually an unsupported language) is preserved. This guarantees the prefetcher never accepts a combination the runtime itself would reject.

Source

Thrown at docling/models/stages/ocr/rapid_ocr_model.py:119

    The pair is routed through _resolve_rapidocr so the prefetcher can never accept a
    combination the runtime would reject, but only the user's own values are kept.
    """
    backend, separator, lang = value.partition(":")
    if not separator or not backend or not lang or ":" in lang:
        raise ValueError(
            f"Invalid RapidOCR model spec {value!r}. "
            "Expected '<backend>:<lang>', e.g. 'onnxruntime:th'."
        )
    if backend not in _RAPIDOCR_BACKENDS:
        raise ValueError(
            f"Unknown RapidOCR backend {backend!r} in {value!r}. "
            f"Supported: {list(_RAPIDOCR_BACKENDS)}."
        )
    try:
        _resolve_rapidocr(lang, backend)
    except ValueError as err:
        raise ValueError(f"Invalid RapidOCR model spec {value!r}: {err}") from err
    return _RapidOcrModelSpec(backend=backend, user_lang=lang)


def _backend_to_engine_type(backend: str) -> "EngineType":
    """Map a docling backend name onto the rapidocr EngineType it stands for."""
    from rapidocr.utils.typings import EngineType

    engine_types = {
        "onnxruntime": EngineType.ONNXRUNTIME,
        "openvino": EngineType.OPENVINO,
        "paddle": EngineType.PADDLE,
        "torch": EngineType.TORCH,
    }
    if backend not in engine_types:
        raise ValueError(
            f"Unknown RapidOCR backend {backend!r}. Supported: {list(_RAPIDOCR_BACKENDS)}."
        )
    return engine_types[backend]

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Use a language code supported by rapidocr for the chosen backend (see the resolution table in rapid_ocr_model.py / rapidocr docs).
  2. If the language is unsupported, pick a different OCR engine that covers it (Tesseract, EasyOCR).
  3. Read the inner {err} message — it names the exact unsupported value to correct.

Example fix

# before
models = ["onnxruntime:zz"]  # unsupported language -> wrapped ValueError

# after
models = ["onnxruntime:th"]  # supported language
Defensive patterns

Strategy: validation

Validate before calling

from docling.models.stages.ocr.rapid_ocr_model import _resolve_rapidocr

def lang_supported(lang: str, backend: str) -> bool:
    try:
        _resolve_rapidocr(lang, backend)
        return True
    except ValueError:
        return False

Try / catch

try:
    specs = [_parse_rapidocr_model_spec(s) for s in raw_specs]
except ValueError as err:
    # err.__cause__ carries the inner unsupported-language reason
    logger.error("Unsupported RapidOCR (backend, lang): %s", err)
    raw_specs = [s for s in raw_specs if s != offending_spec]

Prevention

When it happens

Trigger: A well-formed spec like 'onnxruntime:zz' where the language code is not supported by rapidocr for that backend — _resolve_rapidocr raises and the wrapper converts it into this prefixed ValueError.

Common situations: Requesting languages rapidocr does not ship models for; mixing language codes from other OCR engines; backend-specific language availability differences (a lang valid on onnxruntime but not on paddle).

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/f1c73112294e6b4d. Report an issue: GitHub.