SubtitleEdit/subtitleedit · error · InvalidOperationException

No llama.cpp OCR model found in {LlamaCppServerManager.GetAn

Error message

No llama.cpp OCR model found in {LlamaCppServerManager.GetAndCreateModelsFolder()}. Download one in Subtitle Edit (OCR window > llama.cpp) or pass --ocr-model:<path.gguf>. Curated models: {curatedNames}.

What it means

Thrown when no --ocr-model argument was given and none of the curated OCR models are installed (IsModelInstalled returns false for every entry in LlamaCppServerManager.OcrModels). The engine tries to auto-select the first installed curated model as a default; if nothing is installed, OCR cannot proceed. The message lists the models folder path and curated model names for download guidance.

Source

Thrown at src/seconv/Core/LlamaCppOcrEngine.cs:184

            var model = LlamaCppServerManager.OcrModels.FirstOrDefault(m => m.FileName.Equals(name, StringComparison.OrdinalIgnoreCase))
                        ?? LlamaCppServerManager.OcrModels.FirstOrDefault(m => m.FileName.Equals(name + ".gguf", StringComparison.OrdinalIgnoreCase))
                        ?? LlamaCppServerManager.OcrModels.FirstOrDefault(m => m.DisplayName.Equals(name, StringComparison.OrdinalIgnoreCase));
            if (model == null || !LlamaCppServerManager.IsModelInstalled(model))
            {
                throw new InvalidOperationException(
                    $"OCR model '{name}' not found in {LlamaCppServerManager.GetAndCreateModelsFolder()}. " +
                    "Download one in Subtitle Edit (OCR window > llama.cpp) or pass a full path via --ocr-model. " +
                    $"Curated models: {curatedNames}.");
            }

            return model;
        }

        // No model given: pick the first installed curated OCR model.
        var installed = LlamaCppServerManager.OcrModels.FirstOrDefault(LlamaCppServerManager.IsModelInstalled);
        if (installed == null)
        {
            throw new InvalidOperationException(
                $"No llama.cpp OCR model found in {LlamaCppServerManager.GetAndCreateModelsFolder()}. " +
                "Download one in Subtitle Edit (OCR window > llama.cpp) or pass --ocr-model:<path.gguf>. " +
                $"Curated models: {curatedNames}.");
        }

        return installed;
    }

    private static string? FindMmprojSidecar(string modelPath)
    {
        // Both curated sidecar conventions: "mmproj-<file>" (GLM-OCR, LightOnOCR) and
        // "<stem>-mmproj.gguf" (PaddleOCR-VL).
        var dir = Path.GetDirectoryName(modelPath)!;
        var candidates = new[]
        {
            Path.Combine(dir, "mmproj-" + Path.GetFileName(modelPath)),
            Path.Combine(dir, Path.GetFileNameWithoutExtension(modelPath) + "-mmproj.gguf"),
        };

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Download a curated OCR model via the Subtitle Edit GUI (OCR window > llama.cpp).
  2. Manually download a .gguf OCR model (and its mmproj sidecar) into the models folder shown in the message, then re-run without --ocr-model to auto-select it.
  3. Pass --ocr-model=<full-path.gguf> to use any model outside the curated set.
Defensive patterns

Strategy: validation

Validate before calling

if (!LlamaCppServerManager.OcrModels.Any(LlamaCppServerManager.IsModelInstalled))
{
    Console.Error.WriteLine("No OCR model installed. Download one via SE GUI or pass --ocr-model:<path>.");
    return;
}

Type guard

static bool HasAnyOcrModelInstalled() => LlamaCppServerManager.OcrModels.Any(LlamaCppServerManager.IsModelInstalled);

Try / catch

try { var model = LlamaCppOcrEngine.ResolveModel(null); }
catch (InvalidOperationException ex) when (ex.Message.Contains("No llama.cpp OCR model found"))
{ /* download a curated model or pass --ocr-model:<path> */ }

Prevention

When it happens

Trigger: Running OCR (or a translate/OCR pipeline) without --ocr-model on a system where no curated OCR model .gguf has been downloaded into the models folder.

Common situations: First-time OCR use with no model downloaded; models were cleared/removed; the models folder points to a location that was wiped.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/ee74a5f54ef2efe6. Report an issue: GitHub.