{"record":{"id":"a9961670b45644b3","repo":"SubtitleEdit/subtitleedit","slug":"downloaded-yt-dlp-assetname-failed-sha-256-ver","errorCode":null,"errorMessage":"Downloaded yt-dlp ({assetName}) failed SHA-256 verification — expected {expected}, got {actual}. The file has been removed.","messagePattern":"Downloaded yt-dlp \\((.+?)\\) failed SHA-256 verification — expected (.+?), got (.+?)\\. The file has been removed\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Logic/Download/YtDlpDownloadService.cs","lineNumber":184,"sourceCode":"    /// checksum for <paramref name=\"version\"/>. A tampered, truncated, or\n    /// otherwise corrupt download is deleted and surfaced as an error instead\n    /// of being executed. If no checksum is on record for the asset, this is a\n    /// no-op — we don't block on data we don't have.\n    /// </summary>\n    internal static async Task VerifyChecksumAsync(string filePath, string version, CancellationToken cancellationToken)\n    {\n        var assetName = Path.GetFileName(filePath);\n        if (!KnownSha256.TryGetValue(version, out var byAsset) ||\n            !byAsset.TryGetValue(assetName, out var expected))\n        {\n            return;\n        }\n\n        var actual = await ComputeSha256Async(filePath, cancellationToken);\n        if (!string.Equals(actual, expected, StringComparison.OrdinalIgnoreCase))\n        {\n            TryDeleteFile(filePath);\n            throw new InvalidOperationException(\n                $\"Downloaded yt-dlp ({assetName}) failed SHA-256 verification — expected {expected}, got {actual}. The file has been removed.\");\n        }\n    }\n\n    internal static async Task<string> ComputeSha256Async(string filePath, CancellationToken cancellationToken)\n    {\n        await using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);\n        var hash = await SHA256.HashDataAsync(stream, cancellationToken);\n        return Convert.ToHexString(hash).ToLowerInvariant();\n    }\n\n    private static void TryDeleteFile(string filePath)\n    {\n        try\n        {\n            if (File.Exists(filePath))\n            {\n                File.Delete(filePath);","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Logic/Download/YtDlpDownloadService.cs#L166-L202","documentation":"Thrown by VerifyChecksumAsync in YtDlpDownloadService after a yt-dlp download when the computed SHA-256 of the saved file does not match the pinned expected hash in KnownSha256 for that (version, assetName) pair. The corrupted/tampered file is deleted via TryDeleteFile before the throw, so the next attempt re-downloads.","triggerScenarios":"A completed yt-dlp download whose bytes differ from the pinned checksum: truncated transfer, transparent proxy/MITM, a mirrored/corrupted release, or a yt-dlp version whose KnownSha256 entry was updated to a newer build than what was downloaded.","commonSituations":"Corporate proxy that rewrites binaries, a flaky connection that truncated the download, or a stale KnownSha256 table after yt-dlp published a re-tagged release with the same version number.","solutions":["Retry the download once — transient truncation/network corruption is the most common cause and the bad file is already removed.","If it persists, verify your network path is not MITM'd (compare a manual curl SHA against yt-dlp's published checksum).","Update the KnownSha256 entry to the currently published checksum if upstream re-released the same version.","Confirm Se.DataFolder is writable and not on a filesystem that silently alters bytes (e.g. encoding conversion)."],"exampleFix":"// before\nawait _ytDlp.DownloadYtDlp(progress, ct);\n\n// after: retry once, then surface a clear message\ntry\n{\n    await _ytDlp.DownloadYtDlp(progress, ct);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"SHA-256\"))\n{\n    await _ytDlp.DownloadYtDlp(progress, ct); // bad file was auto-deleted; one retry\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await svc.DownloadYtDlp(progress, ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"SHA-256 verification\"))\n{ await svc.DownloadYtDlp(progress, ct); } // one retry; bad file was auto-deleted","preventionTips":["Keep KnownSha256 in sync with yt-dlp's published checksums after each release.","Avoid networks/proxies that rewrite binaries."],"tags":["yt-dlp","download","sha256","integrity","checksum","network"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}