{"record":{"id":"7b9ee8896208949a","repo":"SubtitleEdit/subtitleedit","slug":"vibevoice-crispasr-model-filename-failed-integ","errorCode":null,"errorMessage":"VibeVoice (CrispASR) model {fileName} failed integrity check (expected SHA-256 {expected}, got {actual}).","messagePattern":"VibeVoice \\(CrispASR\\) model (.+?) failed integrity check \\(expected SHA-256 (.+?), got (.+?)\\)\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/ui/Logic/Download/VibeVoiceCrispAsrDownloadService.cs","lineNumber":126,"sourceCode":"        {\n            return;\n        }\n\n        var expected = DownloadHashManager.GetLatestKnownHash(key);\n        if (string.IsNullOrEmpty(expected))\n        {\n            return;\n        }\n\n        string actual;\n        await using (var stream = File.OpenRead(filePath))\n        {\n            actual = await Sha256Util.ComputeSha256Async(stream, cancellationToken);\n        }\n\n        if (!string.Equals(expected, actual, StringComparison.OrdinalIgnoreCase))\n        {\n            throw new IOException(\n                $\"VibeVoice (CrispASR) model {fileName} failed integrity check (expected SHA-256 {expected}, got {actual}).\");\n        }\n    }\n\n    private static string GetUrl(string fileName)\n    {\n        if (!ModelUrls.TryGetValue(fileName, out var url))\n        {\n            throw new ArgumentException($\"Unknown VibeVoice (CrispASR) model: {fileName}\", nameof(fileName));\n        }\n        return url;\n    }\n\n    private static void TryDelete(string path)\n    {\n        try { File.Delete(path); } catch { /* best-effort cleanup */ }\n    }\n","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Logic/Download/VibeVoiceCrispAsrDownloadService.cs#L108-L144","documentation":"Integrity check for the VibeVoice CrispASR model set. The downloaded file is opened read-only, hashed, and compared to the pinned expected hash; mismatch throws IOException. Surrounding GetUrl also throws ArgumentException for an unknown fileName.","triggerScenarios":"Non-empty expected hash that differs from the SHA-256 of filePath on disk. Empty expected skips the check and returns early.","commonSituations":"Partial/interrupted download, CDN republished the model without bumping the pinned hash, corrupt cache, or a cache that survived a binary update pinning a new hash.","solutions":["Delete the cached model file and re-download.","Verify the pinned expected hash matches the current origin artifact.","Check network/disk for truncation.","If the model was intentionally republished, update the hash constant in VibeVoiceCrispAsrDownloadService."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"var cached = Path.Combine(modelFolder, fileName);\nif (File.Exists(cached))\n{\n    using var s = File.OpenRead(cached);\n    var h = await Sha256Util.ComputeSha256Async(s, ct);\n    if (!string.Equals(expected, h, StringComparison.OrdinalIgnoreCase)) File.Delete(cached);\n}","typeGuard":null,"tryCatchPattern":"try { await service.DownloadModelAsync(...); }\ncatch (IOException ex) when (ex.Message.Contains(\"failed integrity check\"))\n{\n    if (File.Exists(filePath)) File.Delete(filePath);\n    await service.DownloadModelAsync(...);\n}","preventionTips":["Purge the model cache after upgrading the download service binary.","Keep the pinned hash and the origin artifact in sync on republish.","Use a bounded retry for transient download corruption."],"tags":["integrity-check","sha256","download","vibevoice","crispasr","csharp"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}