SubtitleEdit/subtitleedit · error · InvalidOperationException

BinaryOCR database is empty

Error message

BinaryOCR database is empty: {dbPath}

What it means

InvalidOperationException from the BinaryOcrOcrEngine constructor: the .db file exists and loaded, but AllCompareImages is empty — i.e. the database has no trained glyph entries, so recognition would always return nothing. This is distinct from 'file not found' (the file is present but useless).

Solutions

  1. Regenerate the .db in the SE GUI by training on actual subtitle images.
  2. Open the .db in the SE Binary/OCR editor and confirm it has compare images; if empty, retrain.
  3. Use a different, known-good .db (e.g. a Latin.db from another install).

Example fix

// before
if (_db.AllCompareImages.Count == 0)
    throw new InvalidOperationException($"BinaryOCR database is empty: {dbPath}");

// after
if (_db.AllCompareImages.Count == 0)
    throw new InvalidOperationException($"BinaryOCR database '{dbPath}' loaded but has 0 compare images ({_db.AllCompareImages.Count} entries). Retrain it in the SE GUI.");
Defensive patterns

Strategy: validation

Validate before calling

using var probe = new BinaryOcrDb(dbPath, loadCompareImages: true);
if (probe.AllCompareImages.Count == 0)
    throw new InvalidOperationException($"BinaryOCR db '{dbPath}' is empty; retrain in the SE GUI.");

Type guard

static bool OcrDbHasEntries(string path) { using var d = new BinaryOcrDb(path, loadCompareImages: true); return d.AllCompareImages.Count > 0; }

Try / catch

null

Prevention

When it happens

Trigger: Loading a BinaryOCR .db that was created empty, corrupted, or partially written; loadCompareImages:true returned zero compare images.

Common situations: An aborted/cancelled SE GUI training session left a zero-row .db; copied a placeholder .db; format mismatch where the loader skipped all entries silently.

Related errors


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

Appendix: source

Thrown at src/seconv/Core/BinaryOcrOcrEngine.cs:32

    public string Name => "binaryocr";

    private readonly BinaryOcrDb _db;
    private readonly BinaryOcrMatcher _matcher;
    private const int PixelsAreSpaceDefault = 12;
    private const double MaxErrorPercent = 0.5;

    public BinaryOcrOcrEngine(string dbPath)
    {
        if (!File.Exists(dbPath))
        {
            throw new FileNotFoundException(
                $"BinaryOCR database not found: {dbPath}. Use --ocr-db to point to a .db file " +
                "(typically %AppData%\\Subtitle Edit\\OCR\\Latin.db or similar).", dbPath);
        }
        _db = new BinaryOcrDb(dbPath, loadCompareImages: true);
        if (_db.AllCompareImages.Count == 0)
        {
            throw new InvalidOperationException($"BinaryOCR database is empty: {dbPath}");
        }
        _matcher = new BinaryOcrMatcher
        {
            IsLatinDb = Path.GetFileNameWithoutExtension(dbPath).Contains("Latin", StringComparison.OrdinalIgnoreCase),
        };
    }

    public string Recognize(SKBitmap bitmap)
    {
        if (bitmap is null || bitmap.Width == 0 || bitmap.Height == 0)
        {
            return string.Empty;
        }

        var parent = new NikseBitmap2(bitmap);
        parent.MakeTwoColor(200);
        parent.CropTop(0, new SKColor(0, 0, 0, 0));
        var letters = NikseBitmapImageSplitter2.SplitBitmapToLettersNew(

View on GitHub (pinned to 17a9f07487)