SubtitleEdit/subtitleedit · error · IOException

OmniVoice {label} download failed integrity check (expected

Error message

OmniVoice {label} download failed integrity check (expected SHA-256 {expected}, got {actual}).

What it means

OmniVoice engine (not the CrispASR model) integrity check. Unlike the CrispASR variants, the expected hash is fetched dynamically from DownloadHashManager.GetLatestKnownHash(key), allowing the hash to be updated without rebuilding. Mismatch throws IOException.

Source

Thrown at src/ui/Logic/Download/OmniVoiceDownloadService.cs:111

    {
        if (string.IsNullOrEmpty(key) || stream.Length == 0)
        {
            return;
        }

        var expected = DownloadHashManager.GetLatestKnownHash(key);
        if (string.IsNullOrEmpty(expected))
        {
            return;
        }

        stream.Position = 0;
        var actual = await Sha256Util.ComputeSha256Async(stream, cancellationToken);
        stream.Position = 0;

        if (!string.Equals(expected, actual, StringComparison.OrdinalIgnoreCase))
        {
            throw new IOException(
                $"OmniVoice {label} download failed integrity check (expected SHA-256 {expected}, got {actual}).");
        }
    }

    private static string GetUrl(string windowsVariant)
    {
        if (OperatingSystem.IsWindows())
        {
            return windowsVariant switch
            {
                WindowsVariantCuda => WindowsCudaUrl,
                WindowsVariantVulkan => WindowsVulkanUrl,
                _ => WindowsCpuUrl,
            };
        }

        if (OperatingSystem.IsMacOS())
        {

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Force a refresh of DownloadHashManager so it pulls the latest known hash for the key.
  2. Delete and re-download the affected file.
  3. Confirm the origin artifact and the hash-manager entry agree on the same version.
  4. Check network/disk for truncation.
Defensive patterns

Strategy: validation

Validate before calling

var expected = DownloadHashManager.GetLatestKnownHash(key);
if (!string.IsNullOrEmpty(expected))
{
    stream.Position = 0;
    var actual = await Sha256Util.ComputeSha256Async(stream, ct);
    stream.Position = 0;
    if (!string.Equals(expected, actual, StringComparison.OrdinalIgnoreCase))
    {
        // refresh the hash manager, then re-evaluate before failing the user
        await DownloadHashManager.RefreshAsync(ct);
        expected = DownloadHashManager.GetLatestKnownHash(key);
    }
}

Try / catch

try { await service.DownloadAsync(...); }
catch (IOException ex) when (ex.Message.Contains("OmniVoice") && ex.Message.Contains("integrity check"))
{
    await DownloadHashManager.RefreshAsync(ct);
    if (File.Exists(dest)) File.Delete(dest);
    await service.DownloadAsync(...);
}

Prevention

When it happens

Trigger: After download the stream is rewound to position 0, hashed, rewound again, and compared against the manager's latest known hash. A non-empty expected hash that differs from actual triggers the throw.

Common situations: The hash manager holds a stale hash (update channel not refreshed) while the origin already serves a newer build; a partial download; a download cache that survived a version bump in the binary but not in the hash manager.

Related errors


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