subhra74/xdm · error · NonRetriableException
NonResumable
NonResumable
Error message
Resume not supported
What it means
Thrown in PieceGrabber.Connect when a piece's total length is unknown (-1) and the request is not the first request for that stream type. The server did not provide a content length, so the downloader cannot resume into a partial stream and throws NonRetriableException with ErrorCode.NonResumable. This failure is deliberately not retried.
Solutions
- Restart the download from scratch (single connection, no resume) instead of resuming the piece.
- Verify the server supports Content-Length and Range requests; fall back to single-source download if not.
- Ensure IsFirstRequest/stream bookkeeping is correct so length-known first requests are not mistaken for resumes.
Example fix
// before
var piece = callback.GetPiece(pieceId); // Length == -1 on resume -> NonResumable
// after
if (piece.Length == -1) {
// restart download without resume
RestartDownload(disableResume: true);
} Defensive patterns
Strategy: fallback
Validate before calling
var req = new HttpRequestMessage(HttpMethod.Head, url);
var resp = await client.SendAsync(req);
bool canResume = resp.Headers.AcceptRanges.Contains("bytes") && resp.Content.Headers.ContentLength.HasValue;
if (!canResume) disableResume = true; Type guard
bool IsResumable(long pieceLength) => pieceLength != -1;
Try / catch
try { grabber.Connect(); }
catch (DownloadException e) when (e.ErrorCode == ErrorCode.NonResumable) {
RestartDownloadWithoutResume();
} Prevention
- Probe Accept-Ranges/Content-Length before resuming
- Fall back to single-connection download for chunked sources
- Keep stream/first-request bookkeeping accurate
When it happens
Trigger: Calling Connect on a non-first request where callback.GetPiece(...).Length == -1, i.e. a resume attempt against a response with no usable length (chunked transfer or missing Content-Length) for that stream type.
Common situations: Servers that stream with Transfer-Encoding: chunked, dynamic responses (no Content-Length), resuming a download whose original headers no longer advertise a length, misconfigured proxy stripping Content-Length.
Related errors
AI-assisted analysis of subhra74/xdm@1ca5a25aae (2026-09-13).
Data as JSON: /api/errors/b63cc0172525c6f9.
Report an issue: GitHub.
Appendix: source
Thrown at app/XDM/XDM.Core/Downloader/Progressive/PieceGrabber.cs:170
this.sleepHandle.Set();
this.sleepHandle.Close();
this.pieceId = null;
this.callback = null;
try { this.fileWriterStream?.Dispose(); } catch { }
}
private HttpResponse Connect()
{
HttpResponse? response = null;
var error = true;
try
{
if (this.callback == null || this.pieceId == null) throw new OperationCanceledException();
var piece = this.callback.GetPiece(this.pieceId);
var firstRequest = this.callback.IsFirstRequest(piece.StreamType);
if (piece.Length == -1 && !this.callback.IsFirstRequest(piece.StreamType))
throw new NonRetriableException(ErrorCode.NonResumable, "Resume not supported");
var hc = this.callback.GetSharedHttpClient(this.pieceId);
if (hc == null) throw new OperationCanceledException();
request = CreateRequest(hc, piece);
response = hc.Send(request);
CancellationToken.ThrowIfCancellationRequested();
response.EnsureSuccessStatusCode();
var status = response.StatusCode;
var contentLength = response.ContentLength;
if (response.Compressed)
{
contentLength = -1;
if (response.StatusCode == HttpStatusCode.PartialContent)
{
status = HttpStatusCode.OK;
}
}
View on GitHub (pinned to 1ca5a25aae)