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
- Delete the partial download/piece files and restart the download so all pieces are re-fetched completely
- Check available disk space on the target drive; a full disk truncates piece files
- Verify piece file sizes against their expected ranges before assembly and re-download only mismatched pieces
- 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
- Ensure sufficient free disk space before starting large downloads
- Do not manually move/delete piece files between download and assembly
- Validate sizes of resumed piece files before continuing a paused download
- If downloads crash often, restart from scratch instead of trusting stale pieces
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)