immich-app/immich · critical · FileNotFoundError

Recognition charset not found: {charset_path}

Error message

Recognition charset not found: {charset_path}

What it means

`CtcCharSet.from_file` loads the character list used to decode CTC outputs for the OCR model. If the charset file does not exist at the given path it raises FileNotFoundError('Recognition charset not found: {charset_path}'). The ML service cannot start the OCR model without this file, since decoding requires the index-to-character mapping.

Source

Thrown at machine-learning/immich_ml/models/ocr/ctc.py:25


def greedy(outputs: Sequence[NDArray[Any]]) -> tuple[NDArray[np.int32], NDArray[np.float32]]:
    """Models with an in-graph argmax head emit (indices, probs); the rest emit raw logits."""
    if len(outputs) == 2:
        return outputs[0], outputs[1]
    (probs,) = outputs
    indices = probs.argmax(axis=2)
    return indices.astype(np.int32), np.take_along_axis(probs, indices[:, :, None], axis=2)[:, :, 0]


class CtcDecoder:
    def __init__(self, charset: list[str]):
        self.charset = ["", *charset, " "]  # PP-OCR: blank at 0, space last

    @classmethod
    def from_file(cls, charset_path: Path) -> Self:
        if not charset_path.is_file():
            raise FileNotFoundError(f"Recognition charset not found: {charset_path}")
        return cls(charset_path.read_text(encoding="utf-8").splitlines())

    def __len__(self) -> int:
        return len(self.charset)

    def decode(self, indices: NDArray[np.int32], probs: NDArray[np.float32]) -> tuple[list[str], NDArray[np.float32]]:
        keep = np.empty(indices.shape, dtype=bool)
        keep[:, 0] = True
        np.not_equal(indices[:, 1:], indices[:, :-1], out=keep[:, 1:])  # repeats before blanks
        keep &= indices != 0

        scores: NDArray[np.float32] = np.where(keep, probs, 0).sum(1)
        scores /= np.maximum(keep.sum(1), 1)  # an all-blank row sums to 0, so it stays 0
        texts = ["".join(map(self.charset.__getitem__, row[k])) for row, k in zip(indices, keep)]
        return texts, scores

View on GitHub (pinned to 5666d57f15)

Solutions

  1. Check the path in the error and ensure the charset file exists there (ls the path inside the ML container/host).
  2. Reinstall/re-pull the immich ML image or package so bundled model assets are restored.
  3. If using a custom model, copy its dictionary/charset file to the expected path (charset_path) and ensure it's readable.
  4. Fix volume mounts so they don't hide the package assets directory.
  5. Point the model config to the correct directory containing the charset file.

Example fix

# before
docker run ... -v $HOME/models:/app/machines # shadows bundled assets
# after
cp en_dict.txt $HOME/models/ocr/  # or stop shadowing the assets dir
# verify: ls /app/machines/ocr/en_dict.txt inside the container
Defensive patterns

Strategy: validation

Validate before calling

# check the charset file before loading the model
from pathlib import Path
cs = Path(model_dir) / 'en_dict.txt'
if not cs.is_file():
    raise SystemExit(f'missing charset file: {cs} - reinstall ML assets or copy model dict')

Type guard

def charset_file_ok(path) -> bool:
    from pathlib import Path
    p = Path(path)
    return p.is_file() and p.stat().st_size > 0

Try / catch

try:
    charset = CtcCharSet.from_file(charset_path)
except FileNotFoundError as e:
    logger.error(str(e))
    raise SystemExit('OCR charset missing; reinstall model assets or fix model_dir')

Prevention

When it happens

Trigger: Starting the immich_ml service with the OCR model enabled while the charset asset (e.g. en_dict.txt / ppocr charset file) is missing from the installed package or the mounted volume; a custom model directory lacking the charset file; Docker image built without the asset; wrong charset_path configured for a custom/local model.

Common situations: Partially copied or pruned installation missing model assets; running from source without downloading model files; custom PaddleOCR model with its own dict file that wasn't placed next to the model; volume mounts shadowing the package's assets directory.

Related errors


AI-assisted analysis of immich-app/immich@5666d57f15 (2026-09-01). Data as JSON: /api/errors/c37cbf2643cfa667. Report an issue: GitHub.