beeradmoore/dlss-swapper · error · Exception

Downloaded file was invalid.

Error message

Downloaded file was invalid.

What it means

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.

Solutions

  1. Retry the download to rule out transient corruption
  2. Verify the file's MD5 manually against the upstream release and update ZipMD5Hash in the manifest
  3. Update the app/manifest to the latest version with corrected hashes
  4. Check proxy/AV interference if corruption reproduces consistently

Example fix

// before
if (ZipMD5Hash != fileStream.GetMD5Hash())
{
    throw new Exception("Downloaded file was invalid.");
}
// after
var actualHash = fileStream.GetMD5Hash();
if (!string.Equals(ZipMD5Hash, actualHash, StringComparison.OrdinalIgnoreCase))
{
    throw new Exception($"Downloaded file MD5 '{actualHash}' did not match expected '{ZipMD5Hash}'.");
}
Defensive patterns

Strategy: retry

Validate before calling

// after download, verify before the library does
fileStream.Position = 0;
var hash = fileStream.GetMD5Hash();
if (!string.Equals(hash, expectedZipMd5, StringComparison.OrdinalIgnoreCase))
    File.Delete(tempZipFile); // force clean re-download

Try / catch

try
{
    await dllRecord.DownloadAsync();
}
catch (Exception ex) when (ex.Message == "Downloaded file was invalid.")
{
    File.Delete(tempZipPath);
    await dllRecord.DownloadAsync(); // retry once; if it recurs, the manifest hash is stale
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of beeradmoore/dlss-swapper@ab9b1e2d4b (2026-09-15). Data as JSON: /api/errors/66d39c36eacaa0df. Report an issue: GitHub.

Appendix: source

Thrown at src/Data/DLLRecord.cs:300

        try
        {
            LocalRecord.FileDownloader = fileDownloader;
            NotifyPropertyChanged(nameof(LocalRecord));


            using (var fileStream = new FileStream(tempZipFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None, FileDownloader.BufferSize, true))
            {
                var didDownload = await LocalRecord.FileDownloader.DownloadFileToStreamAsync(fileStream, cancellationToken).ConfigureAwait(false);

                if (didDownload == false)
                {
                    throw new Exception("Could not download file.");
                }

                if (ZipMD5Hash != fileStream.GetMD5Hash())
                {
                    throw new Exception("Downloaded file was invalid.");
                }

                fileStream.Position = 0;

                using (var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read, true))
                {
                    DLLManager.HandleExtractFromZip(zipArchive, this);
                }
            }

            App.CurrentApp.RunOnUIThread(() =>
            {
                LocalRecord.IsDownloaded = true;
                NotifyPropertyChanged(nameof(LocalRecord));
            });

            return (true, string.Empty, false);
        }

View on GitHub (pinned to ab9b1e2d4b)