{"record":{"id":"cf659e0d6fe4fe8a","repo":"nilaoda/N_m3u8DL-RE","slug":"resstring-badm3u8","errorCode":null,"errorMessage":"ResString.badM3u8","messagePattern":"ResString\\.badM3u8","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs","lineNumber":43,"sourceCode":"        this.ParserConfig = parserConfig;\n        this.M3u8Url = parserConfig.Url ?? string.Empty;\n        this.SetBaseUrl();\n    }\n\n    private void SetBaseUrl()\n    {\n        this.BaseUrl = !string.IsNullOrEmpty(ParserConfig.BaseUrl) ? ParserConfig.BaseUrl : this.M3u8Url;\n    }\n\n    /// <summary>\n    /// 预处理m3u8内容\n    /// </summary>\n    public void PreProcessContent()\n    {\n        M3u8Content = M3u8Content.Trim();\n        if (!M3u8Content.StartsWith(HLSTags.ext_m3u))\n        {\n            throw new Exception(ResString.badM3u8);\n        }\n\n        foreach (var p in ParserConfig.ContentProcessors)\n        {\n            if (p.CanProcess(ExtractorType, M3u8Content, ParserConfig))\n            {\n                M3u8Content = p.Process(M3u8Content, ParserConfig);\n            }\n        }\n    }\n\n    /// <summary>\n    /// 预处理URL\n    /// </summary>\n    public string PreProcessUrl(string url)\n    {\n        foreach (var p in ParserConfig.UrlProcessors)\n        {","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/nilaoda/N_m3u8DL-RE/blob/e113dee70c924ee08dae5460624909b04d84cb76/src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs#L25-L61","documentation":"HLSExtractor.PreProcessContent validates that the downloaded playlist text starts with the '#EXTM3U' tag (HLSTags.ext_m3u) and throws the localized ResString.badM3u8 message if it does not. This guards the extractor from parsing HTML error pages, JSON API responses, or other non-playlist content as an M3U8.","triggerScenarios":"Constructing HLSExtractor and calling ExtractStreamsAsync/LoadM3u8FromUrlAsync with content whose trimmed first line is not '#EXTM3U'.","commonSituations":"The playlist URL points at a login/anti-bot HTML page, the server returns a 403/404 page with HTTP 200, the URL is a DASH .mpd or plain media segment rather than an HLS playlist, or content was double-decoded/encrypted.","solutions":["Print/log the beginning of M3u8Content to see what was actually fetched (usually an HTML error page).","Fix the playlist URL — it must return a real HLS manifest starting with '#EXTM3U'.","Add required headers/cookies (Referer, User-Agent) via ParserConfig so the server stops returning an error page.","If the content is DASH, use the DASH extractor instead of the HLS one.","Catch the error and show the localized ResString.badM3u8 message to the user."],"exampleFix":"// before\nvar extractor = new HLSExtractor(parserConfig);\nvar streams = await extractor.LoadM3u8FromUrlAsync(new Uri(url));\n\n// after\nparserConfig.Headers[\"User-Agent\"] = \"Mozilla/5.0 ...\";\nparserConfig.Headers[\"Referer\"] = pageUrl;\nvar content = await http.GetStringAsync(url);\nif (!content.TrimStart().StartsWith(\"#EXTM3U\"))\n    throw new Exception($\"URL did not return an M3U8 playlist: {content[..80]}...\");","handlingStrategy":"validation","validationCode":"var content = await DownloadPlaylistAsync(url);\nif (!content.TrimStart().StartsWith(\"#EXTM3U\"))\n    throw new InvalidDataException($\"Not an M3U8 playlist (got: {content[..Math.Min(80, content.Length)]}...)\");","typeGuard":"static bool LooksLikeM3u8(string content) =>\n    !string.IsNullOrWhiteSpace(content) && content.TrimStart().StartsWith(\"#EXTM3U\");","tryCatchPattern":"try { var streams = await extractor.ExtractStreamsAsync(rawText); }\ncatch (Exception ex) when (ex.Message == ResString.badM3u8)\n{ /* show user: URL did not return an HLS playlist */ }","preventionTips":["Check the response's first line for '#EXTM3U' before extraction.","Send proper User-Agent/Referer/cookie headers so servers don't return HTML error pages.","Use the DASH extractor for .mpd URLs, HLS extractor only for HLS manifests."],"tags":["hls","m3u8","parsing","validation"],"backgroundTag":"unexpected-response-shape","analyzedSha":"e113dee70c924ee08dae5460624909b04d84cb76","analyzedAt":"2026-09-13T02:43:21.078Z","contentChangedAt":"2026-09-13T02:43:21.078Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}