{"record":{"id":"66d39c36eacaa0df","repo":"beeradmoore/dlss-swapper","slug":"downloaded-file-was-invalid","errorCode":null,"errorMessage":"Downloaded file was invalid.","messagePattern":"Downloaded file was invalid\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/Data/DLLRecord.cs","lineNumber":300,"sourceCode":"\n        try\n        {\n            LocalRecord.FileDownloader = fileDownloader;\n            NotifyPropertyChanged(nameof(LocalRecord));\n\n\n            using (var fileStream = new FileStream(tempZipFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None, FileDownloader.BufferSize, true))\n            {\n                var didDownload = await LocalRecord.FileDownloader.DownloadFileToStreamAsync(fileStream, cancellationToken).ConfigureAwait(false);\n\n                if (didDownload == false)\n                {\n                    throw new Exception(\"Could not download file.\");\n                }\n\n                if (ZipMD5Hash != fileStream.GetMD5Hash())\n                {\n                    throw new Exception(\"Downloaded file was invalid.\");\n                }\n\n                fileStream.Position = 0;\n\n                using (var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read, true))\n                {\n                    DLLManager.HandleExtractFromZip(zipArchive, this);\n                }\n            }\n\n            App.CurrentApp.RunOnUIThread(() =>\n            {\n                LocalRecord.IsDownloaded = true;\n                NotifyPropertyChanged(nameof(LocalRecord));\n            });\n\n            return (true, string.Empty, false);\n        }","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/beeradmoore/dlss-swapper/blob/ab9b1e2d4bb04187c48fe58eeea06c2b0ea71fbb/src/Data/DLLRecord.cs#L282-L318","documentation":"After a successful download, DownloadAsync computes the MD5 of the downloaded zip and compares it to the record's expected ZipMD5Hash from the manifest; a mismatch throws this error because the package cannot be trusted/verified. The library never extracts an archive that fails hash verification.","triggerScenarios":"Downloaded zip's MD5 differs from DLLRecord.ZipMD5Hash — upstream replaced the file without updating the manifest hash, the download was truncated/corrupted in transit, a proxy/AV modified the body, or the manifest pins a stale hash.","commonSituations":"New upstream release published while manifest still lists the old hash; flaky connection dropping bytes; corporate proxy or antivirus re-compressing/altering downloads; manifest updated with hash of a differently-encoded file.","solutions":["Retry the download to rule out transient corruption","Verify the file's MD5 manually against the upstream release and update ZipMD5Hash in the manifest","Update the app/manifest to the latest version with corrected hashes","Check proxy/AV interference if corruption reproduces consistently"],"exampleFix":"// before\nif (ZipMD5Hash != fileStream.GetMD5Hash())\n{\n    throw new Exception(\"Downloaded file was invalid.\");\n}\n// after\nvar actualHash = fileStream.GetMD5Hash();\nif (!string.Equals(ZipMD5Hash, actualHash, StringComparison.OrdinalIgnoreCase))\n{\n    throw new Exception($\"Downloaded file MD5 '{actualHash}' did not match expected '{ZipMD5Hash}'.\");\n}","handlingStrategy":"retry","validationCode":"// after download, verify before the library does\nfileStream.Position = 0;\nvar hash = fileStream.GetMD5Hash();\nif (!string.Equals(hash, expectedZipMd5, StringComparison.OrdinalIgnoreCase))\n    File.Delete(tempZipFile); // force clean re-download","typeGuard":null,"tryCatchPattern":"try\n{\n    await dllRecord.DownloadAsync();\n}\ncatch (Exception ex) when (ex.Message == \"Downloaded file was invalid.\")\n{\n    File.Delete(tempZipPath);\n    await dllRecord.DownloadAsync(); // retry once; if it recurs, the manifest hash is stale\n}","preventionTips":["Retry once on hash mismatch to rule out transient corruption","Update manifest hashes whenever upstream republishes packages","Check proxy/AV tools that alter downloaded content","Compare downloaded size against Content-Length before hashing"],"tags":["checksum","md5","download","integrity"],"backgroundTag":"checksum-mismatch","analyzedSha":"ab9b1e2d4bb04187c48fe58eeea06c2b0ea71fbb","analyzedAt":"2026-09-15T05:25:32.979Z","contentChangedAt":"2026-09-15T05:25:32.979Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}