SubtitleEdit/subtitleedit · error · IOException

CosyVoice3 (CrispASR) model {fileName} failed integrity chec

Error message

CosyVoice3 (CrispASR) model {fileName} failed integrity check (expected SHA-256 {expected}, got {actual}).

What it means

Thrown by the CosyVoice3 CrispASR integrity check after the model file has been (re)downloaded. The service computes SHA-256 of the downloaded file and compares it case-insensitively against the expected hash stored for that fileName. A mismatch means the bytes on disk do not match the trusted reference and the file is treated as corrupt/tampered. IOException wraps it so the download pipeline can treat it as a retryable I/O failure.

Source

Thrown at src/ui/Logic/Download/CosyVoice3CrispAsrDownloadService.cs:161

        {
            return;
        }

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

        string actual;
        await using (var stream = File.OpenRead(filePath))
        {
            actual = await Sha256Util.ComputeSha256Async(stream, cancellationToken);
        }

        if (!string.Equals(expected, actual, StringComparison.OrdinalIgnoreCase))
        {
            throw new IOException(
                $"CosyVoice3 (CrispASR) model {fileName} failed integrity check (expected SHA-256 {expected}, got {actual}).");
        }
    }

    private static string GetUrl(string fileName)
    {
        if (!ModelUrls.TryGetValue(fileName, out var url))
        {
            throw new ArgumentException($"Unknown CosyVoice3 (CrispASR) model: {fileName}", nameof(fileName));
        }
        return url;
    }

    private static void TryDelete(string path)
    {
        try { File.Delete(path); } catch { /* best-effort cleanup */ }
    }

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Delete the cached file at filePath so the service re-downloads it fresh, then retry.
  2. If the mismatch persists after a clean re-download, the expected hash may be outdated — verify the fileName maps to the correct expected value and update it to match the upstream artifact.
  3. Check the download URL/mirror for tampering or proxy interception, and re-run over a clean network path.
  4. Confirm the file is not being modified concurrently (e.g. by AV or sync clients) while the hash is computed.

Example fix

// before: stale/corrupt cached file trips the check
await cosyVoice3Service.DownloadAsync(fileName, path, progress, ct);

// after: force a clean re-download when integrity fails
if (File.Exists(path)) File.Delete(path);
await cosyVoice3Service.DownloadAsync(fileName, path, progress, ct);
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: confirm file exists and (optionally) hash before trusting it
if (!File.Exists(filePath)) { /* let download proceed */ }
// Full pre-validation requires computing the hash, which IS the check itself — see try/catch instead.

Try / catch

try { await cosyVoice3Service.VerifyAsync(fileName, filePath, expected, ct); }
catch (IOException ex) when (ex.Message.Contains("failed integrity check"))
{
    File.Delete(filePath); // purge corrupt artifact
    await cosyVoice3Service.DownloadAsync(fileName, filePath, progress, ct); // one clean retry
}

Prevention

When it happens

Trigger: Calling the verify step with a fileName whose downloaded bytes hash to a value != expected: truncated download, mirror corruption, MITM/proxy rewriting the body, disk write error, wrong file placed at filePath, or a stale expected hash after an upstream model bump.

Common situations: A mirror CDN served a stale/corrupt artifact; antivirus stripped bytes; user manually dropped a different model file with the same name; the expected-hash table was bumped for a new model release but the old file is cached on disk; partial download that reported 200 but short body.

Related errors


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