nilaoda/N_m3u8DL-RE · error · Exception
Failed to execute action after
Error message
Failed to execute action after {maxRetries} retries. What it means
WebRequestRetryAsync exhausts all retry attempts for the supplied action and still has no successful result, so it gives up and throws, wrapping the last underlying exception as InnerException. It exists so callers get one clear, self-describing failure after retries instead of a silent loop.
Solutions
- Inspect the InnerException (currentException) to find the real root cause — the wrapper message only says retries ran out.
- Increase maxRetries and/or retryDelayMilliseconds/retryDelayIncrementMilliseconds to tolerate transient outages.
- Check network connectivity, proxy settings and the target server's health before retrying the operation.
- For persistent 4xx/5xx responses, fix the request itself (URL, auth, headers) rather than retrying.
Example fix
// before
var data = await RetryUtil.WebRequestRetryAsync(() => DownloadAsync(url), maxRetries: 2);
// after
try
{
var data = await RetryUtil.WebRequestRetryAsync(() => DownloadAsync(url), maxRetries: 5, retryDelayMilliseconds: 1000, retryDelayIncrementMilliseconds: 500);
}
catch (Exception ex)
{
Log.Error(ex.InnerException, "Download failed after all retries");
throw;
} Defensive patterns
Strategy: retry
Validate before calling
using var ping = new HttpClient();
var ok = (await ping.GetAsync(url)).IsSuccessStatusCode;
if (!ok) throw new HttpRequestException("Endpoint unhealthy before starting retry loop"); Try / catch
try
{
result = await RetryUtil.WebRequestRetryAsync(action, maxRetries, retryDelayMilliseconds);
}
catch (Exception ex)
{
var root = ex.InnerException ?? ex; // real cause
Log.Error(root, "All {Retries} attempts failed", maxRetries);
} Prevention
- Always log InnerException — the wrapper message hides the root cause.
- Size maxRetries and backoff to the endpoint's known reliability.
- Check server/network health before launching long retry loops.
When it happens
Trigger: Calling WebRequestRetryAsync with an action (typically an HTTP request) that keeps throwing (network failure, 5xx, timeout) for maxRetries consecutive attempts; after each failure it delays retryDelayMilliseconds plus the linear backoff increment.
Common situations: Remote server or CDN down/slow, flaky network or DNS, rate limiting returning 503, TLS/proxy problems, or maxRetries configured too low for a slow endpoint.
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
AI-assisted analysis of nilaoda/N_m3u8DL-RE@e113dee70c (2026-09-13).
Data as JSON: /api/errors/04b39ed13fccb2f8.
Report an issue: GitHub.
Appendix: source
Thrown at src/N_m3u8DL-RE.Common/Util/RetryUtil.cs:33
while (retryCount < maxRetries)
{
try
{
result = await funcAsync();
break;
}
catch (Exception ex) when (ex is WebException or IOException or HttpRequestException)
{
currentException = ex;
retryCount++;
Logger.WarnMarkUp($"[grey]{ex.Message.EscapeMarkup()} ({retryCount}/{maxRetries})[/]");
await Task.Delay(retryDelayMilliseconds + (retryDelayIncrementMilliseconds * (retryCount - 1)));
}
}
if (retryCount == maxRetries)
{
throw new Exception($"Failed to execute action after {maxRetries} retries.", currentException);
}
return result;
}
}View on GitHub (pinned to e113dee70c)