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
- Force a refresh of DownloadHashManager so it pulls the latest known hash for the key.
- Delete and re-download the affected file.
- Confirm the origin artifact and the hash-manager entry agree on the same version.
- 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
- Refresh DownloadHashManager on startup so expected hashes track the latest artifacts.
- Delete cached downloads after upgrading to a new engine version.
- Log both expected and actual hashes on mismatch to speed diagnosis.
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
- OmniVoice (CrispASR) model {fileName} failed integrity check
- Qwen3 TTS {label} download failed integrity check (expected
- MOSS-TTS (CrispASR) model {fileName} failed integrity check
- Qwen3 TTS (CrispASR) model {fileName} failed integrity check
- VibeVoice (CrispASR) model {fileName} failed integrity check
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/70d60e231a8212b6.
Report an issue: GitHub.