{"record":{"id":"db3cda57eec7d8e6","repo":"subhra74/xdm","slug":"generic","errorCode":"Generic","errorMessage":"Unexpected EOF :: {piece.Id}","messagePattern":"Unexpected EOF :: (.+?)","errorType":"error_code","errorClass":"DownloadException","httpStatus":null,"severity":"error","filePath":"app/XDM/XDM.Core/Downloader/Progressive/PieceGrabber.cs","lineNumber":289,"sourceCode":"                    if (remaining <= 0)\r\n                    {\r\n                        if (maxByteRange > 0 && this.callback.ContinueAdjacentPiece(this.pieceId, maxByteRange))\r\n                        {\r\n                            piece = this.callback.GetPiece(this.pieceId);\r\n                            remaining = piece.Length - piece.Downloaded;\r\n                        }\r\n                        else\r\n                        {\r\n                            CloseUnfinishedRequest(count);\r\n                            break;\r\n                        }\r\n                    }\r\n                    var x = sourceStream.Read(BUF, 0,\r\n                        (int)Math.Min(BUF.Length, remaining));\r\n                    this.CancellationToken.ThrowIfCancellationRequested();\r\n                    if (x == 0)\r\n                    {\r\n                        throw new DownloadException(ErrorCode.Generic, \"Unexpected EOF :: \" + piece.Id);\r\n                    }\r\n                    try\r\n                    {\r\n                        targetStream.Write(BUF, 0, x);\r\n                        count += x;\r\n                    }\r\n                    catch (IOException ioe)\r\n                    {\r\n                        Log.Debug(ioe, \"Disk error\");\r\n                        throw new NonRetriableException(ErrorCode.DiskError, \"Disk error :: \" + piece.Id, ioe);\r\n                    }\r\n                    if (this.CancellationToken.IsCancellationRequested) return;\r\n                    this.callback?.UpdateDownloadedBytesCount(this.pieceId, x);\r\n                    this.callback?.ThrottleIfNeeded();\r\n                }\r\n            }\r\n            finally\r\n            {\r","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/subhra74/xdm/blob/1ca5a25aae007826c859c81bea494e7c102e1242/app/XDM/XDM.Core/Downloader/Progressive/PieceGrabber.cs#L271-L307","documentation":"In PieceGrabber.CopyWithFixedLength, the read loop expects a known number of bytes; if sourceStream.Read returns 0 before 'remaining' reaches zero, the network stream ended prematurely. The grabber throws DownloadException with ErrorCode.Generic and the piece id, indicating a truncated transfer.","triggerScenarios":"The HTTP response body ends before the expected piece length: server closes connection early, connection dropped mid-transfer, or Content-Length promised more bytes than actually sent.","commonSituations":"Unstable Wi-Fi/mobile connections dropping mid-transfer, aggressive server/proxy idle timeouts killing long reads, CDN edge disconnects, VPN interruptions during large downloads.","solutions":["Retry the download - the outer PieceGrabber loop will reconnect and request the remaining range.","Increase retry count/delay (Config.Instance.MaxRetry, RetryDelay) for unstable networks.","Use a wired/stable connection or disable power-management on the network adapter for long transfers.","Verify the server serves the full range reliably; test with curl -r and compare byte counts."],"exampleFix":"// before\nvar x = sourceStream.Read(BUF, 0, (int)Math.Min(BUF.Length, remaining));\nif (x == 0) throw new DownloadException(ErrorCode.Generic, \"Unexpected EOF :: \" + piece.Id);\n// after\nvar x = sourceStream.Read(BUF, 0, (int)Math.Min(BUF.Length, remaining));\nif (x == 0) {\n    if (remaining > 0 && retryCount++ < maxReconnects) { ReconnectAndContinue(); return; }\n    throw new DownloadException(ErrorCode.Generic, \"Unexpected EOF :: \" + piece.Id);\n}","handlingStrategy":"retry","validationCode":"// prefer servers/proxies with reliable keep-alive; before long downloads\nif (!NetworkInterface.GetIsNetworkAvailable()) await WaitForNetworkAsync();","typeGuard":null,"tryCatchPattern":"try { Download(); }\ncatch (DownloadException e) when (e.Message.StartsWith(\"Unexpected EOF\")) {\n    await Task.Delay(backoff);\n    ResumeFromLastGoodOffset();\n}","preventionTips":["Use stable connections for large downloads","Increase retry count/delay for flaky networks","Avoid proxies that time out long idle reads","Keep pieces small so EOF loses less work"],"tags":["network","eof","truncated-response"],"backgroundTag":"broken-pipe","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"}