nilaoda/N_m3u8DL-RE · error · Exception

Download first segment failed!

Error message

Download first segment failed!

What it means

SimpleDownloadManager.DownloadStreamAsync throws when the first media segment download fails (Success != false check on the DownloadResult). It is a hard stop because subsequent segment handling (indexing, MSS init repair) depends on the first segment.

Solutions

  1. Retry the command — first failure is often transient network error
  2. Check the first segment URL with curl (signed URL may have expired)
  3. Ensure the temp directory has free disk space and write permissions
  4. Re-fetch the playlist to get fresh segment URLs
Defensive patterns

Strategy: retry

Validate before calling

// check disk and first-segment URL before downloading
if (new DriveInfo(tmpDir).AvailableFreeSpace < 500_000_000) throw new IOException("low disk space");

Type guard

static bool IsSuccess(DownloadResult r) => r is { Success: true };

Try / catch

try { await DownloadStreamAsync(...); }
catch (Exception ex) when (ex.Message == "Download first segment failed!")
{
    logger.Warn("first segment failed; refreshing playlist and retrying");
    playlist = await RefreshPlaylistAsync();
    await DownloadStreamAsync(...);
}

Prevention

When it happens

Trigger: Downloader.DownloadSegmentAsync returns a result with Success == false for the first segment (seg.Index == first) — HTTP error, timeout, disk write failure at the tmp path.

Common situations: Segment URL expired or CDN 403/404, network interruption at download start, disk full in tmp directory, wrong extension handling causing path errors.

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 nilaoda/N_m3u8DL-RE@e113dee70c (2026-09-13). Data as JSON: /api/errors/52dac2dc7a72ef56. Report an issue: GitHub.

Appendix: source

Thrown at src/N_m3u8DL-RE/DownloadManager/SimpleDownloadManager.cs:236

            }
        }

        // 计算填零个数
        var pad = "0".PadLeft(segments.Count().ToString().Length, '0');

        // 下载第一个分片
        if (!readInfo || StreamExtractor.ExtractorType == ExtractorType.MSS)
        {
            var seg = segments.First();
            segments = segments.Skip(1);

            var index = seg.Index;
            var path = Path.Combine(tmpDir, index.ToString(pad) + $".{streamSpec.Extension ?? "clip"}.tmp");
            var result = await Downloader.DownloadSegmentAsync(seg, path, speedContainer, headers);
            FileDic[seg] = result;
            if (result is not { Success: true })
            {
                throw new Exception("Download first segment failed!");
            }
            task.Increment(1);
            if (result is { Success: true })
            {
                // 修复MSS init
                if (StreamExtractor.ExtractorType == ExtractorType.MSS)
                {
                    var processor = new MSSMoovProcessor(streamSpec);
                    var header = processor.GenHeader(File.ReadAllBytes(result.ActualFilePath));
                    await File.WriteAllBytesAsync(FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath, header);
                    if (seg.IsEncrypted && DownloaderConfig.MyOptions.MP4RealTimeDecryption && !string.IsNullOrEmpty(currentKID))
                    {
                        // 需要重新解密init
                        var enc = FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath;
                        var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
                        var dResult = await MP4DecryptUtil.DecryptAsync(decryptEngine, decryptionBinaryPath, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID);
                        if (dResult)
                        {

View on GitHub (pinned to e113dee70c)