{"record":{"id":"3488d22a6d6b1b05","repo":"SubtitleEdit/subtitleedit","slug":"voxcpm2-crispasr-model-filename-failed-integri","errorCode":null,"errorMessage":"VoxCPM2 (CrispASR) model {fileName} failed integrity check (expected SHA-256 {expected}, got {actual}).","messagePattern":"VoxCPM2 \\(CrispASR\\) model (.+?) failed integrity check \\(expected SHA-256 (.+?), got (.+?)\\)\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/ui/Logic/Download/VoxCPM2CrispAsrDownloadService.cs","lineNumber":136,"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                $\"VoxCPM2 (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 VoxCPM2 (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":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Logic/Download/VoxCPM2CrispAsrDownloadService.cs#L118-L154","documentation":"Integrity check for the VoxCPM2 CrispASR model set, structurally identical to the other CrispASR services. File is opened read-only, hashed, compared case-insensitively to the pinned expected hash; mismatch throws IOException.","triggerScenarios":"Non-empty expected hash that differs from the computed SHA-256 of filePath. Empty expected short-circuits.","commonSituations":"Truncated download, CDN artifact swap without hash bump, corrupt local cache, or stale cache after a binary update.","solutions":["Delete the cached model file and re-download.","Confirm 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 VoxCPM2CrispAsrDownloadService."],"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":["Delete cached model files after a binary version bump.","Verify the pinned hash matches the published artifact before release.","Use a bounded retry for transient download corruption."],"tags":["integrity-check","sha256","download","voxcpm2","crispasr","csharp"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}