subhra74/xdm · error · Exception
Invalid response code
Error message
Invalid response code: {statusCode.Value} What it means
MultiSourceHLSDownloader.ProbeTarget downloads the HLS manifest and, when the download fails, inspects captured HTTP error statuses via FindErrorStatus. If a status code was recorded it throws an Exception 'Invalid response code: N' with an inner HttpException carrying that status.
Solutions
- Read the inner HttpException's status code: 403/401 means refresh cookies or signed URLs from the browser, 404 means the manifest URL is stale
- Re-extract the m3u8 URL from the page; CDN playlists rotate and old URLs expire quickly
- Retry with backoff if the code is 429/5xx (rate limiting or transient server issues)
- Ensure required headers (Referer, User-Agent, Origin) captured with the video match what the CDN expects
Example fix
// before
throw new Exception($"Invalid response code: {statusCode.Value}",
new HttpException(statusCode.Value.ToString(), null, statusCode.Value));
// after
var code = (int)statusCode.Value;
if (code == 403 || code == 401)
throw new DownloadException(ErrorCode.AuthExpired, $"HLS manifest auth failed ({code}) - refresh URL/cookies");
throw new Exception($"Invalid response code: {statusCode.Value}",
new HttpException(statusCode.Value.ToString(), null, statusCode.Value)); Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight the manifest URL before probing
using (var resp = await http.GetAsync(manifestUrl))
{
if (!resp.IsSuccessStatusCode)
Log.Warn($"HLS manifest pre-check failed: {(int)resp.StatusCode}");
} Try / catch
try
{
downloader.ProbeTarget();
}
catch (Exception ex) when (ex.InnerException is HttpException he)
{
int code = (int)he.StatusCode;
if (code == 401 || code == 403) RefreshSignedUrl();
else if (code == 429) await Task.Delay(TimeSpan.FromSeconds(30));
throw;
} Prevention
- Re-capture m3u8 URLs shortly before download; signed CDN URLs expire fast
- Send the same Referer/User-Agent/Origin headers the player used
- Back off and retry on 429/5xx responses
- Test the manifest URL with curl before starting the HLS download
When it happens
Trigger: ProbeTarget (invoked while building the playlists dictionary) receives failed segment/manifest downloads and FindErrorStatus() returns a known HTTP error status, e.g. 403/404 from the HLS server.
Common situations: HLS master/media playlist URL returns 403 due to expired tokens/signed URLs; 404 because the playlist was removed; CDN geo-blocking; rate limiting (429) under heavy segment requests.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- response.StatusDescription
- Unable to download HLS manifest
- InvalidResponse
- NonResumable
- Connectivity error
AI-assisted analysis of subhra74/xdm@1ca5a25aae (2026-09-13).
Data as JSON: /api/errors/036f3a2522b1ff93.
Report an issue: GitHub.
Appendix: source
Thrown at app/XDM/XDM.Core/Downloader/Adaptive/Hls/MultiSourceHLSDownloader.cs:188
if (status.Length == 2)
{
if (status[0] != HttpStatusCode.OK) return status[0];
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;
View on GitHub (pinned to 1ca5a25aae)