SubtitleEdit/subtitleedit · error · InvalidOperationException

OCR model file not found: {name}

Error message

OCR model file not found: {name}

What it means

Thrown when the --ocr-model argument is a path (rooted or containing a directory separator) pointing to a .gguf model file, but that file does not exist (File.Exists returns false). The OCR engine resolves paths directly — a non-existent model file path is an immediate hard failure since there is nothing to load.

Source

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

    /// Resolves <c>--ocr-model</c> to an installed model: a full <c>.gguf</c> path (needs its
    /// mmproj vision-projector sidecar next to it), a curated OCR model by file/display name,
    /// or - when omitted - the first installed curated OCR model.
    /// </summary>
    internal static LlamaCppModel ResolveOcrModel(string? requestedModel)
    {
        var curatedNames = string.Join(", ", LlamaCppServerManager.OcrModels.Select(m => m.FileName));

        if (!string.IsNullOrWhiteSpace(requestedModel))
        {
            var name = requestedModel.Trim();

            // Full path to a .gguf: use it directly, but require the mmproj sidecar - a vision
            // model served without its projector can't see the image at all.
            if (Path.IsPathRooted(name) || name.Contains(Path.DirectorySeparatorChar) || name.Contains(Path.AltDirectorySeparatorChar))
            {
                if (!File.Exists(name))
                {
                    throw new InvalidOperationException($"OCR model file not found: {name}");
                }

                var fullPath = Path.GetFullPath(name);
                var mmproj = FindMmprojSidecar(fullPath);
                if (mmproj == null)
                {
                    var fileName = Path.GetFileName(fullPath);
                    var stem = Path.GetFileNameWithoutExtension(fullPath);
                    throw new InvalidOperationException(
                        $"No vision projector found next to {fullPath}. llama.cpp OCR models need their mmproj sidecar; " +
                        $"expected 'mmproj-{fileName}' or '{stem}-mmproj.gguf' in the same folder.");
                }

                return new LlamaCppModel(Path.GetFileName(fullPath), fullPath, string.Empty, Url: string.Empty,
                    MmprojFileName: mmproj);
            }

            // Name: match the curated OCR models (with or without .gguf).

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Verify the path with File.Exists before passing it; check for typos and correct the directory.
  2. Use an absolute path to avoid working-directory ambiguity: --ocr-model=/home/user/models/model.gguf.
  3. Alternatively, pass just the curated model name (without directory separators) to let seconv resolve it from the models folder.

Example fix

// before
var model = LlamaCppOcrEngine.ResolveModel("/wrong/path/model.gguf");

// after
var model = LlamaCppOcrEngine.ResolveModel("/correct/path/model.gguf");
Defensive patterns

Strategy: validation

Validate before calling

if (Path.IsPathRooted(name) || name.Contains(Path.DirectorySeparatorChar))
{
    if (!File.Exists(name))
        throw new InvalidOperationException($"OCR model file not found: {name}");
}

Type guard

static bool IsModelFileReadable(string name) => !Path.IsPathRooted(name) && !name.Contains(Path.DirectorySeparatorChar) || File.Exists(name);

Try / catch

try { var model = LlamaCppOcrEngine.ResolveModel(modelArg); }
catch (InvalidOperationException ex) when (ex.Message.Contains("OCR model file not found"))
{ /* correct the path or use a curated model name */ }

Prevention

When it happens

Trigger: Passing --ocr-model=/path/to/model.gguf where the path is wrong, the file was deleted, or the relative path resolved from an unexpected working directory. The path is detected as a full/relative file path (via Path.IsPathRooted or directory separator presence) rather than a curated model name.

Common situations: Typo in the model path; the model was downloaded to a different directory; a relative path that breaks when CWD changes; pointing at a symlink that dangles.

Related errors


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