subhra74/xdm · error · Exception
Unable to download HLS manifest
Error message
Unable to download HLS manifest
What it means
The fallback branch of MultiSourceHLSDownloader.ProbeTarget: when the HLS manifest download failed but FindErrorStatus() found no specific HTTP status code, XDM throws 'Unable to download HLS manifest'. This indicates a failure to fetch the manifest without an identifiable HTTP error response (e.g. connectivity loss or an exception without a captured status).
Solutions
- Check basic network connectivity to the manifest host (curl the m3u8 URL to reproduce)
- Verify the m3u8 URL is current; re-capture it from the page if the download is old
- Check proxy/firewall/TLS interception that can break the request without a clean HTTP status
- Retry the download; transient network failures surface as this unspecific error
Example fix
// before
throw new Exception("Unable to download HLS manifest");
// after
Log.Warn("HLS manifest fetch failed without an HTTP status; likely network error");
throw new DownloadException(ErrorCode.NetworkFailure,
"Unable to download HLS manifest (no HTTP status captured; check connectivity)"); Defensive patterns
Strategy: retry
Validate before calling
// Confirm the manifest is reachable before calling ProbeTarget
var probe = await http.SendAsync(new HttpRequestMessage(HttpMethod.Head, manifestUrl));
if (!probe.IsSuccessStatusCode)
throw new InvalidOperationException($"Manifest unreachable: {(int)probe.StatusCode}"); Try / catch
try
{
downloader.ProbeTarget();
}
catch (Exception ex) when (ex.Message == "Unable to download HLS manifest")
{
Log.Warn("HLS manifest fetch failed without HTTP status; retrying after network check");
await WaitForNetworkAsync();
downloader.ProbeTarget();
} Prevention
- Verify network connectivity/DNS before starting HLS downloads
- Check proxy, VPN, and TLS interception which cause failures with no HTTP status
- Validate the m3u8 URL is current before probing
- Retry with backoff; this unspecific failure is often transient
When it happens
Trigger: ProbeTarget's manifest download task completes with success=false and FindErrorStatus() returns null/HasValue==false, so no HTTP status is attributed to the failure.
Common situations: Network drop or DNS failure while fetching the m3u8; TLS errors; server closing the connection mid-response; proxy failures; manifest host unreachable.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
AI-assisted analysis of subhra74/xdm@1ca5a25aae (2026-09-13).
Data as JSON: /api/errors/c3d5cf9d1a03c0cb.
Report an issue: GitHub.
Appendix: source
Thrown at app/XDM/XDM.Core/Downloader/Adaptive/Hls/MultiSourceHLSDownloader.cs:191
if (status[1] != HttpStatusCode.OK) return status[1];
return null;
}
else
{
if (status[0] != HttpStatusCode.OK) return status[0];
return null;
}
}
if (!success)
{
var statusCode = FindErrorStatus();
if (statusCode.HasValue)
{
throw new Exception($"Invalid response code: {statusCode.Value}",
new HttpException(statusCode.Value.ToString(), null, statusCode.Value));
}
throw new Exception("Unable to download HLS manifest");
}
var playlists = new Dictionary<string, HlsPlaylist>();
if (state.Demuxed)
{
playlists["video"] = HlsParser.ParseMediaSegments(results[0]!.Split('\n'), state.NonMuxedVideoPlaylistUrl.ToString());
playlists["audio"] = HlsParser.ParseMediaSegments(results[1]!.Split('\n'), state.NonMuxedAudioPlaylistUrl.ToString());
this._state.VideoContainerFormat = GuessContainerFormatFromPlaylist(playlists["video"]);
this._state.AudioContainerFormat = GuessContainerFormatFromPlaylist(playlists["audio"]);
var ext = FileExtensionHelper.GuessContainerFormatFromSegmentExtension(
this._state.VideoContainerFormat, this._state.AudioContainerFormat);
TargetFileName = Path.GetFileNameWithoutExtension(TargetFileName ?? "video")
+ ext;
Log.Debug($"Guessed Demuxed formats - VideoContainerFormat: {this._state.VideoContainerFormat} AudioContainerFormat: {this._state.AudioContainerFormat}");
Log.Debug($"Guessed - ext: {ext} TargetFileName: {TargetFileName}");
View on GitHub (pinned to 1ca5a25aae)