subhra74/xdm · error · DownloadException
MaxRetryFailed
MaxRetryFailed
Error message
Max retry exceeded
What it means
PieceGrabber retries a failing download loop up to Config.Instance.MaxRetry times. Each caught failure increments timesRetried and, when the counter exceeds MaxRetry, the grabber throws DownloadException with ErrorCode.MaxRetryFailed. It means the piece repeatedly failed to connect or transfer and the library has given up retrying.
Solutions
- Increase Config.Instance.MaxRetry to allow more attempts on unstable networks.
- Increase Config.Instance.RetryDelay to give the server/network time to recover between attempts.
- Check network stability (proxy, VPN, firewall) and retry the download manually.
- Wrap download orchestration to catch MaxRetryFailed and restart the download from persisted pieces.
Example fix
// before var cfg = Config.Instance; // MaxRetry = 3 // after var cfg = Config.Instance; cfg.MaxRetry = 10; // tolerate unstable links cfg.RetryDelay = 5; // seconds between attempts
Defensive patterns
Strategy: retry
Validate before calling
// before starting
if (Config.Instance.MaxRetry < 5) Config.Instance.MaxRetry = 5;
if (!NetworkInterface.GetIsNetworkAvailable()) throw new InvalidOperationException("No network"); Try / catch
try { downloader.Download(); }
catch (DownloadException e) when (e.ErrorCode == ErrorCode.MaxRetryFailed) {
Log.Warn("Giving up after max retries");
ScheduleRetryWithBackoff();
} Prevention
- Configure MaxRetry >= 5 for mobile/unstable links
- Set a sensible RetryDelay (3-10s)
- Monitor network availability before/ during downloads
- Persist piece state so restarts resume, not restart
When it happens
Trigger: The inner download block throws a retryable exception (network drop, connection reset, timeout) more than MaxRetry consecutive times inside PieceGrabber's loop; cancellation and non-retriable exceptions (AssembleFailedException, NonRetriableException, OperationCanceledException) are rethrown instead and never reach this path.
Common situations: Flaky or throttled network connections, servers that keep rejecting range requests, MaxRetry configured too low (default small) on unreliable links, firewalls/proxies intermittently killing persistent connections.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- Connectivity error
- response.StatusDescription
- Invalid response code
- Unable to download HLS manifest
- EOF :: File corrupted
AI-assisted analysis of subhra74/xdm@1ca5a25aae (2026-09-13).
Data as JSON: /api/errors/b9256fde332cb813.
Report an issue: GitHub.
Appendix: source
Thrown at app/XDM/XDM.Core/Downloader/Progressive/PieceGrabber.cs:116
catch (HttpException e)
{
var status = e.StatusCode;
if (Enum.IsDefined(typeof(HttpStatusCode), status))
{
throw new DownloadException(ErrorCode.InvalidResponse,
"Invalid response: " + e.Message, e);
}
}
catch (Exception e)
{
if (e is KeyNotFoundException || this.CancellationToken.IsCancellationRequested) return;
if (e is AssembleFailedException || e is NonRetriableException || e is OperationCanceledException) throw;
Log.Debug(e, "Error in PieceGrabber inner block - swallowing error - isCancelled: " + this.cancellationTokenSource.IsCancellationRequested);
}
timesRetried++;
if (timesRetried > Config.Instance.MaxRetry)
{
throw new DownloadException(ErrorCode.MaxRetryFailed, "Max retry exceeded");
}
if (connectPhase)
{
sleep(Config.Instance.RetryDelay * 1000);
CancellationToken.ThrowIfCancellationRequested();
//await Task.Delay(Config.Instance.RetryDelay * 1000,
// this.CancellationToken).ConfigureAwait(false);
}
}
}
catch (Exception e)
{
if (e is KeyNotFoundException || this.CancellationToken.IsCancellationRequested)
{
return;
}
Log.Debug(e, "Error in PieceGrabber outer block");
if (this.pieceId != null)
View on GitHub (pinned to 1ca5a25aae)