{"record":{"id":"296ff4399cb2986a","repo":"iawia002/lux","slug":"this-page-has-no-playlist","errorCode":null,"errorMessage":"this page has no playlist","messagePattern":"this page has no playlist","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extractors/bilibili/bilibili.go","lineNumber":190,"sourceCode":"\t\t\tsubtitle: fmt.Sprintf(\"%s %s\", u.Title, u.LongTitle),\n\t\t}\n\t\tgo func(index int, options bilibiliOptions, extractedData []*extractors.Data) {\n\t\t\tdefer wgp.Done()\n\t\t\textractedData[index] = bilibiliDownload(options, extractOption)\n\t\t}(dataIndex, options, extractedData)\n\t\tdataIndex++\n\t}\n\twgp.Wait()\n\treturn extractedData, nil\n}\n\nfunc getMultiPageData(html string) (*multiPage, error) {\n\tvar data multiPage\n\tmultiPageDataString := utils.MatchOneOf(\n\t\thtml, `window.__INITIAL_STATE__=(.+?);\\(function`,\n\t)\n\tif multiPageDataString == nil {\n\t\treturn &data, errors.New(\"this page has no playlist\")\n\t}\n\terr := json.Unmarshal([]byte(multiPageDataString[1]), &data)\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\treturn &data, nil\n}\n\nfunc extractFestival(url, html string, extractOption extractors.Options) ([]*extractors.Data, error) {\n\tmatches := utils.MatchAll(html, \"<\\\\s*script[^>]*>\\\\s*window\\\\.__INITIAL_STATE__=([\\\\s\\\\S]*?);\\\\s?\\\\(function[\\\\s\\\\S]*?<\\\\/\\\\s*script\\\\s*>\")\n\tif len(matches) < 1 {\n\t\treturn nil, errors.WithStack(extractors.ErrURLParseFailed)\n\t}\n\tif len(matches[0]) < 2 {\n\t\treturn nil, errors.New(\"could not find video in page\")\n\t}\n\n\tvar festivalData festival","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/iawia002/lux/blob/dd00f6d258d80b6684a0b9402d7124e5c18ef42f/extractors/bilibili/bilibili.go#L172-L208","documentation":"bilibili.getMultiPageData scrapes the window.__INITIAL_STATE__ JSON that Bilibili embeds in multi-part video pages, via the pattern window.__INITIAL_STATE__=(.+?);(function. The error means the fetched HTML contained no such script, so playlist metadata could not be parsed for a URL routed down the multi-page path. Transport succeeded; the page body was simply not the expected video page.","triggerScenarios":"A multi-page bilibili URL whose response is a region-locked or risk-control (waf) interstitial instead of the video page; a single-part video page that carries no playlist state; a Bilibili template change that drops or renames __INITIAL_STATE__.","commonSituations":"Datacenter IPs triggering Bilibili verification; expired or removed multi-part IDs; Bilibili A/B changes to the embedded state format; requests sent without cookies.","solutions":["Open the URL in an incognito browser and confirm it renders an episode list for logged-out users.","If the video is single-part, use the plain video URL so the single-video code path runs instead of the playlist path.","Re-run with a browser cookie (lux -c cookie.txt) to get past risk control.","If the page still embeds the state but in a new shape, update the regex in getMultiPageData."],"exampleFix":"// before\ndata, err := extractors.Extract(url, opts)\n// after — a playlist miss on a single-part video: retry the plain video URL\nif err != nil && strings.Contains(err.Error(), \"this page has no playlist\") {\n\tdata, err = extractors.Extract(plainVideoURL(url), opts)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isNoPlaylist(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"this page has no playlist\")\n}","tryCatchPattern":"Catch errors from the bilibili extractor; if isNoPlaylist(err) is true, fall back to extracting the plain (single-part) video URL rather than failing the whole batch. Any other error propagates.","preventionTips":["Verify the URL shows an episode list in an incognito browser before adding it to a batch","Supply a fresh browser cookie when extracting many bilibili URLs from one IP","Group single-part and multi-part URLs separately so one bad page cannot abort the run"],"tags":["bilibili","html-parsing","playlist","scraping","risk-control"],"backgroundTag":null,"analyzedSha":"dd00f6d258d80b6684a0b9402d7124e5c18ef42f","analyzedAt":"2026-08-15T16:57:31.080Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}