SubtitleEdit/subtitleedit · error · Exception

{engine.Error}

Error message

{engine.Error}

What it means

Thrown in OcrGroupsWithCrispEmbed after attempting to start the CrispEmbed engine: StartCliPipeline (for detector+recognizer backends) or StartServerAsync (for VLM backends) returned false, and engine.Error holds the reason. A false return means the server/CLI process could not be launched or did not become ready, so scanning frames is impossible and the method aborts before RunLlmOcr.

Solutions

  1. Read engine.Error in the exception message for the concrete startup failure.
  2. Confirm CrispEmbedEngine.GetCliExecutable()/GetServerExecutable() return existing, executable files.
  3. Verify backend.GetModelPath/GetDetectorPath point at complete (non-partial) model files; re-download if needed.
  4. Free the server port / kill stale crispembed-server processes, and ensure the required runtime (CUDA/CPU) is installed.

Example fix

// before
var started = backend.UsesTextDetector
    ? engine.StartCliPipeline(CrispEmbedEngine.GetCliExecutable(), backend.GetModelPath(model.Model), backend.GetDetectorPath(model.Model))
    : await engine.StartServerAsync(CrispEmbedEngine.GetServerExecutable(), backend.GetModelPath(model.Model), cancellationToken);
if (!started) throw new Exception(engine.Error);

// after - preflight paths so the error names the missing file
var cli = CrispEmbedEngine.GetCliExecutable();
var modelPath = backend.GetModelPath(model.Model);
if (!File.Exists(cli)) throw new Exception("CrispEmbed CLI not found: " + cli);
if (!File.Exists(modelPath)) throw new Exception("CrispEmbed model not found: " + modelPath);
var started = backend.UsesTextDetector
    ? engine.StartCliPipeline(cli, modelPath, backend.GetDetectorPath(model.Model))
    : await engine.StartServerAsync(CrispEmbedEngine.GetServerExecutable(), modelPath, cancellationToken);
if (!started) throw new Exception(engine.Error);
Defensive patterns

Strategy: validation

Validate before calling

var cli = CrispEmbedEngine.GetCliExecutable();
var modelPath = backend.GetModelPath(model.Model);
if (!File.Exists(cli)) throw new Exception("CrispEmbed CLI not found: " + cli);
if (!File.Exists(modelPath)) throw new Exception("CrispEmbed model not found: " + modelPath);

Try / catch

try
{
    var started = backend.UsesTextDetector ? engine.StartCliPipeline(...) : await engine.StartServerAsync(...);
    if (!started) throw new Exception(engine.Error);
}
catch (Exception ex) { SeLogger.Error(ex, "CrispEmbed engine failed to start"); /* show message */ }

Prevention

When it happens

Trigger: CrispEmbed CLI executable or server executable missing/not executable; the model/detector path is wrong or the file is corrupt; the server failed to bind its port or crashed during startup; a timeout waiting for the server to become ready; missing runtime dependency (e.g. CUDA/runtime for the GGUF).

Common situations: Backend chosen but its executable was deleted/renamed; model download incomplete so GetModelPath points at a partial file; port already in use by a stale server process; GPU runtime missing for a GPU backend.

Related errors


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

Appendix: source

Thrown at src/ui/Features/Video/VideoOcr/VideoOcrViewModel.cs:1015

        {
            throw new Exception(Se.Language.Ocr.CrispEmbedNotDownloaded);
        }

        using var engine = new CrispEmbedOcr(Se.Settings.Ocr.CrispEmbedOcrTimeoutMinutes);

        var started = backend.UsesTextDetector
            ? engine.StartCliPipeline(
                CrispEmbedEngine.GetCliExecutable(),
                backend.GetModelPath(model.Model),
                backend.GetDetectorPath(model.Model))
            : await engine.StartServerAsync(
                CrispEmbedEngine.GetServerExecutable(),
                backend.GetModelPath(model.Model),
                cancellationToken);

        if (!started)
        {
            throw new Exception(engine.Error);
        }

        await RunLlmOcr(ocrGroups, group => OcrWithBitmap(group, bitmap => engine.Ocr(bitmap, cancellationToken)),
            () => engine.Error, reportProgress, addPreviewLine, cancellationToken);
    }

    private static async Task<string> OcrWithBitmap(VideoOcrFrameGroup group, Func<SKBitmap, Task<string>> ocr)
    {
        using var bitmap = SKBitmap.Decode(group.RepresentativeFileName);
        if (bitmap == null)
        {
            return string.Empty;
        }

        return await ocr(bitmap);
    }

    private static async Task RunLlmOcr(

View on GitHub (pinned to 17a9f07487)