subhra74/xdm · error · Exception

EOF :: File corrupted

Error message

EOF :: File corrupted

What it means

DualSourceHTTPDownloader.AssemblePieces concatenates downloaded pieces into the final file while streaming from part-file streams (infs) to the output stream (outfs). If a read returns 0 bytes before the expected remaining length (len) is satisfied, the piece file is short/corrupt and XDM throws 'EOF :: File corrupted'.

Solutions

  1. Delete the partial download/piece files and restart the download so all pieces are re-fetched completely
  2. Check available disk space on the target drive; a full disk truncates piece files
  3. Verify piece file sizes against their expected ranges before assembly and re-download only mismatched pieces
  4. If using resumable downloads, validate integrity (sizes/checksums) of existing pieces instead of blindly resuming

Example fix

// before
var x = infs.Read(buf, 0, (int)Math.Min(buf.Length, len));
if (x == 0)
    throw new Exception("EOF :: File corrupted");
// after
var x = infs.Read(buf, 0, (int)Math.Min(buf.Length, len));
if (x == 0)
{
    Log.Warn($"Piece stream ended early; {len} bytes still expected - marking piece for re-download");
    MarkPieceCorrupt(currentPieceIndex);
    throw new InvalidDataException($"Piece {currentPieceIndex} is truncated (EOF before {len} expected bytes)");
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate piece file sizes against expected ranges before assembly
foreach (var piece in pieces)
{
    var actual = new FileInfo(piece.Path).Length;
    if (actual != piece.ExpectedLength)
        throw new InvalidDataException($"Piece {piece.Index} truncated: {actual}/{piece.ExpectedLength} bytes");
}

Try / catch

try
{
    downloader.AssemblePieces();
}
catch (Exception ex) when (ex.Message == "EOF :: File corrupted")
{
    Log.Warn("Truncated piece detected; deleting piece files and re-downloading");
    downloader.DeletePartialPieces();
    downloader.RestartDownload();
}

Prevention

When it happens

Trigger: During AssemblePieces, infs.Read returns 0 (end of stream) while len bytes were still expected from the current piece, meaning the stored piece is smaller than its declared range.

Common situations: Download interrupted leaving truncated piece files; disk full during piece writing; piece file deleted or modified externally between download and assembly; application crash mid-download then resume with stale pieces.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of subhra74/xdm@1ca5a25aae (2026-09-13). Data as JSON: /api/errors/7f51272553d759af. Report an issue: GitHub.

Appendix: source

Thrown at app/XDM/XDM.Core/Downloader/Progressive/DualHttp/DualSourceHTTPDownloader.cs:527

                        }
                        catch (IOException ioe)
                        {
                            throw new AssembleFailedException(ErrorCode.DiskError, ioe);
                        }
                        totalBytes += x;
                        bytes += x;
                    }
                }
                else
                {
                    while (len > 0)
                    {
                        if (this.cancelFlag.IsCancellationRequested) return;
                        var x = infs.Read(buf, 0, (int)Math.Min(buf.Length, len));
                        if (x == 0)
                        {
                            Log.Debug("EOF :: File corrupted");
                            throw new Exception("EOF :: File corrupted");
                        }
                        try
                        {
                            outfs.Write(buf, 0, x);
                        }
                        catch (IOException ioe)
                        {
                            throw new AssembleFailedException(ErrorCode.DiskError, ioe);
                        }
                        len -= x;
                        totalBytes += x;
                        bytes += x;
                        if (streamSize > 0)
                        {
                            var progress = (int)Math.Ceiling(totalBytes * 100 / (double)streamSize * 3);
                            if (progress > 100) progress = 100;
                            this.OnAssembleProgressChanged(progress);
                        }

View on GitHub (pinned to 1ca5a25aae)