iawia002/lux · error

this page has no playlist

Error message

this page has no playlist

What it means

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.

Source

Thrown at extractors/bilibili/bilibili.go:190

			subtitle: fmt.Sprintf("%s %s", u.Title, u.LongTitle),
		}
		go func(index int, options bilibiliOptions, extractedData []*extractors.Data) {
			defer wgp.Done()
			extractedData[index] = bilibiliDownload(options, extractOption)
		}(dataIndex, options, extractedData)
		dataIndex++
	}
	wgp.Wait()
	return extractedData, nil
}

func getMultiPageData(html string) (*multiPage, error) {
	var data multiPage
	multiPageDataString := utils.MatchOneOf(
		html, `window.__INITIAL_STATE__=(.+?);\(function`,
	)
	if multiPageDataString == nil {
		return &data, errors.New("this page has no playlist")
	}
	err := json.Unmarshal([]byte(multiPageDataString[1]), &data)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	return &data, nil
}

func extractFestival(url, html string, extractOption extractors.Options) ([]*extractors.Data, error) {
	matches := utils.MatchAll(html, "<\\s*script[^>]*>\\s*window\\.__INITIAL_STATE__=([\\s\\S]*?);\\s?\\(function[\\s\\S]*?<\\/\\s*script\\s*>")
	if len(matches) < 1 {
		return nil, errors.WithStack(extractors.ErrURLParseFailed)
	}
	if len(matches[0]) < 2 {
		return nil, errors.New("could not find video in page")
	}

	var festivalData festival

View on GitHub (pinned to dd00f6d258)

Solutions

  1. Open the URL in an incognito browser and confirm it renders an episode list for logged-out users.
  2. If the video is single-part, use the plain video URL so the single-video code path runs instead of the playlist path.
  3. Re-run with a browser cookie (lux -c cookie.txt) to get past risk control.
  4. If the page still embeds the state but in a new shape, update the regex in getMultiPageData.

Example fix

// before
data, err := extractors.Extract(url, opts)
// after — a playlist miss on a single-part video: retry the plain video URL
if err != nil && strings.Contains(err.Error(), "this page has no playlist") {
	data, err = extractors.Extract(plainVideoURL(url), opts)
}
Defensive patterns

Strategy: try-catch

Type guard

func isNoPlaylist(err error) bool {
	return err != nil && strings.Contains(err.Error(), "this page has no playlist")
}

Try / catch

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.

Prevention

When it happens

Trigger: 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__.

Common situations: Datacenter IPs triggering Bilibili verification; expired or removed multi-part IDs; Bilibili A/B changes to the embedded state format; requests sent without cookies.

Related errors


AI-assisted analysis of iawia002/lux@dd00f6d258 (2026-08-15). Data as JSON: /api/errors/296ff4399cb2986a. Report an issue: GitHub.