{"record":{"id":"e915b20bdc8fdf5f","repo":"SubtitleEdit/subtitleedit","slug":"cosyvoice3-crispasr-model-filename-failed-inte","errorCode":null,"errorMessage":"CosyVoice3 (CrispASR) model {fileName} failed integrity check (expected SHA-256 {expected}, got {actual}).","messagePattern":"CosyVoice3 \\(CrispASR\\) model (.+?) failed integrity check \\(expected SHA-256 (.+?), got (.+?)\\)\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/ui/Logic/Download/CosyVoice3CrispAsrDownloadService.cs","lineNumber":161,"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                $\"CosyVoice3 (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 CosyVoice3 (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":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Logic/Download/CosyVoice3CrispAsrDownloadService.cs#L143-L179","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Delete the cached file at filePath so the service re-downloads it fresh, then retry.","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.","Check the download URL/mirror for tampering or proxy interception, and re-run over a clean network path.","Confirm the file is not being modified concurrently (e.g. by AV or sync clients) while the hash is computed."],"exampleFix":"// before: stale/corrupt cached file trips the check\nawait cosyVoice3Service.DownloadAsync(fileName, path, progress, ct);\n\n// after: force a clean re-download when integrity fails\nif (File.Exists(path)) File.Delete(path);\nawait cosyVoice3Service.DownloadAsync(fileName, path, progress, ct);","handlingStrategy":"try-catch","validationCode":"// Pre-check: confirm file exists and (optionally) hash before trusting it\nif (!File.Exists(filePath)) { /* let download proceed */ }\n// Full pre-validation requires computing the hash, which IS the check itself — see try/catch instead.","typeGuard":null,"tryCatchPattern":"try { await cosyVoice3Service.VerifyAsync(fileName, filePath, expected, ct); }\ncatch (IOException ex) when (ex.Message.Contains(\"failed integrity check\"))\n{\n    File.Delete(filePath); // purge corrupt artifact\n    await cosyVoice3Service.DownloadAsync(fileName, filePath, progress, ct); // one clean retry\n}","preventionTips":["Always re-download after a model/version bump instead of trusting cached bytes.","Compute and log the actual hash on mismatch to compare against the expected value.","Pin expected hashes in code/registry and bump them atomically with the model URL."],"tags":["integrity","sha256","cosyvoice3","crispasr","download","corruption"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}