SubtitleEdit/subtitleedit · error · IOException

IndexTTS (CrispASR) model {fileName} failed integrity check

Error message

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

What it means

Thrown by the IndexTTS CrispASR integrity check: the SHA-256 of the file at filePath does not case-insensitively match the expected hash registered for that fileName. IOException is used so the pipeline treats it as an I/O-layer fault (retryable). A mismatch signals corruption, truncation, tampering, or a stale expected hash.

Source

Thrown at src/ui/Logic/Download/IndexTtsCrispAsrDownloadService.cs:143

        {
            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(
                $"IndexTTS (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 IndexTTS (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 and re-download.
  2. Verify the expected hash matches the current upstream artifact for fileName; update the registry if a new release shipped.
  3. Re-download from a clean network / alternate mirror to rule out in-transit corruption.
  4. Ensure no AV/sync process touches the file during the hash computation.

Example fix

// before
await indexTtsService.DownloadAsync(fileName, path, progress, ct);

// after
if (File.Exists(path)) File.Delete(path);
await indexTtsService.DownloadAsync(fileName, path, progress, ct);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!File.Exists(filePath)) { /* allow download */ }

Try / catch

try { await indexTtsService.VerifyAsync(fileName, filePath, expected, ct); }
catch (IOException ex) when (ex.Message.Contains("failed integrity check"))
{ File.Delete(filePath); await indexTtsService.DownloadAsync(fileName, filePath, progress, ct); }

Prevention

When it happens

Trigger: Downloaded bytes for fileName hash to something other than expected; a partial/corrupt file is cached at filePath; the mirror served a different artifact; the expected-hash registry was bumped for a new model but old bytes remain on disk; concurrent file modification during hashing.

Common situations: Old cache from a prior app version after a model update; CDN served a corrupt/stale artifact; AV altered the file; user replaced the file with a same-named different model.

Related errors


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