{"record":{"id":"782881c9f34d2b9d","repo":"SubtitleEdit/subtitleedit","slug":"qwen3-tts-label-download-failed-integrity-check","errorCode":null,"errorMessage":"Qwen3 TTS {label} download failed integrity check (expected SHA-256 {expected}, got {actual}).","messagePattern":"Qwen3 TTS (.+?) download failed integrity check \\(expected SHA-256 (.+?), got (.+?)\\)\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/ui/Logic/Download/Qwen3TtsCppDownloadService.cs","lineNumber":96,"sourceCode":"    {\n        if (string.IsNullOrEmpty(key) || stream.Length == 0)\n        {\n            return;\n        }\n\n        var expected = DownloadHashManager.GetLatestKnownHash(key);\n        if (string.IsNullOrEmpty(expected))\n        {\n            return;\n        }\n\n        stream.Position = 0;\n        var actual = await Sha256Util.ComputeSha256Async(stream, cancellationToken);\n        stream.Position = 0;\n\n        if (!string.Equals(expected, actual, StringComparison.OrdinalIgnoreCase))\n        {\n            throw new IOException(\n                $\"Qwen3 TTS {label} download failed integrity check (expected SHA-256 {expected}, got {actual}).\");\n        }\n    }\n\n    public async Task DownloadModels(string modelsFolder, string ttsModelFileName, IProgress<float>? progress, Action<string>? titleProgress, CancellationToken cancellationToken)\n    {\n        if (!TtsModelUrls.TryGetValue(ttsModelFileName, out var ttsModelUrl))\n        {\n            throw new ArgumentException($\"Unknown Qwen3 TTS model: {ttsModelFileName}\", nameof(ttsModelFileName));\n        }\n\n        var ttsModelPath = Path.Combine(modelsFolder, ttsModelFileName);\n        var tokenizerPath = Path.Combine(modelsFolder, TokenizerModelFileName);\n        var needTts = !File.Exists(ttsModelPath);\n        var needTokenizer = !File.Exists(tokenizerPath);\n        var total = (needTts ? 1 : 0) + (needTokenizer ? 1 : 0);\n        var step = 0;\n","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Logic/Download/Qwen3TtsCppDownloadService.cs#L78-L114","documentation":"Integrity check for the Qwen3 TTS (cpp) engine download. Expected hash comes from DownloadHashManager.GetLatestKnownHash(key); the freshly downloaded stream is hashed in place (rewound to 0 before and after) and compared case-insensitively. Mismatch throws IOException.","triggerScenarios":"A non-empty expected hash from the manager that differs from the SHA-256 of the downloaded stream. Empty expected skips the check.","commonSituations":"Stream not actually rewound before hashing elsewhere (here it is), a partial download, an updated origin artifact that the hash manager hasn't tracked yet, or a corrupt cache.","solutions":["Refresh DownloadHashManager so the latest known hash matches the current artifact.","Delete and re-download the affected file.","Verify the engine artifact version the binary expects vs. the one the CDN serves.","Check for truncation from network/disk."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var expected = DownloadHashManager.GetLatestKnownHash(key);\nif (!string.IsNullOrEmpty(expected))\n{\n    stream.Position = 0;\n    var actual = await Sha256Util.ComputeSha256Async(stream, ct);\n    stream.Position = 0;\n    if (!string.Equals(expected, actual, StringComparison.OrdinalIgnoreCase))\n    {\n        await DownloadHashManager.RefreshAsync(ct);\n    }\n}","typeGuard":null,"tryCatchPattern":"try { await service.DownloadAsync(...); }\ncatch (IOException ex) when (ex.Message.Contains(\"Qwen3 TTS\") && ex.Message.Contains(\"integrity check\"))\n{\n    await DownloadHashManager.RefreshAsync(ct);\n    if (File.Exists(dest)) File.Delete(dest);\n    await service.DownloadAsync(...);\n}","preventionTips":["Refresh the hash manager before validating freshly downloaded engine files.","Always rewind the stream to 0 before hashing (the code does this; preserve it on edits).","Delete cached engine files after a binary version bump."],"tags":["integrity-check","sha256","download","qwen3-tts","hash-manager","csharp"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}