{"record":{"id":"7f51272553d759af","repo":"subhra74/xdm","slug":"eof-file-corrupted","errorCode":null,"errorMessage":"EOF :: File corrupted","messagePattern":"EOF :: File corrupted","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"app/XDM/XDM.Core/Downloader/Progressive/DualHttp/DualSourceHTTPDownloader.cs","lineNumber":527,"sourceCode":"                        }\r\n                        catch (IOException ioe)\r\n                        {\r\n                            throw new AssembleFailedException(ErrorCode.DiskError, ioe);\r\n                        }\r\n                        totalBytes += x;\r\n                        bytes += x;\r\n                    }\r\n                }\r\n                else\r\n                {\r\n                    while (len > 0)\r\n                    {\r\n                        if (this.cancelFlag.IsCancellationRequested) return;\r\n                        var x = infs.Read(buf, 0, (int)Math.Min(buf.Length, len));\r\n                        if (x == 0)\r\n                        {\r\n                            Log.Debug(\"EOF :: File corrupted\");\r\n                            throw new Exception(\"EOF :: File corrupted\");\r\n                        }\r\n                        try\r\n                        {\r\n                            outfs.Write(buf, 0, x);\r\n                        }\r\n                        catch (IOException ioe)\r\n                        {\r\n                            throw new AssembleFailedException(ErrorCode.DiskError, ioe);\r\n                        }\r\n                        len -= x;\r\n                        totalBytes += x;\r\n                        bytes += x;\r\n                        if (streamSize > 0)\r\n                        {\r\n                            var progress = (int)Math.Ceiling(totalBytes * 100 / (double)streamSize * 3);\r\n                            if (progress > 100) progress = 100;\r\n                            this.OnAssembleProgressChanged(progress);\r\n                        }\r","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/subhra74/xdm/blob/1ca5a25aae007826c859c81bea494e7c102e1242/app/XDM/XDM.Core/Downloader/Progressive/DualHttp/DualSourceHTTPDownloader.cs#L509-L545","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nvar x = infs.Read(buf, 0, (int)Math.Min(buf.Length, len));\nif (x == 0)\n    throw new Exception(\"EOF :: File corrupted\");\n// after\nvar x = infs.Read(buf, 0, (int)Math.Min(buf.Length, len));\nif (x == 0)\n{\n    Log.Warn($\"Piece stream ended early; {len} bytes still expected - marking piece for re-download\");\n    MarkPieceCorrupt(currentPieceIndex);\n    throw new InvalidDataException($\"Piece {currentPieceIndex} is truncated (EOF before {len} expected bytes)\");\n}","handlingStrategy":"validation","validationCode":"// Validate piece file sizes against expected ranges before assembly\nforeach (var piece in pieces)\n{\n    var actual = new FileInfo(piece.Path).Length;\n    if (actual != piece.ExpectedLength)\n        throw new InvalidDataException($\"Piece {piece.Index} truncated: {actual}/{piece.ExpectedLength} bytes\");\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    downloader.AssemblePieces();\n}\ncatch (Exception ex) when (ex.Message == \"EOF :: File corrupted\")\n{\n    Log.Warn(\"Truncated piece detected; deleting piece files and re-downloading\");\n    downloader.DeletePartialPieces();\n    downloader.RestartDownload();\n}","preventionTips":["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"],"tags":["download","file-corruption","pieces","io"],"backgroundTag":"file-read-failed","analyzedSha":"1ca5a25aae007826c859c81bea494e7c102e1242","analyzedAt":"2026-09-13T20:37:40.968Z","contentChangedAt":"2026-09-13T20:37:40.968Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}