{"record":{"id":"e80a470c86917080","repo":"ytdl-org/youtube-dl","slug":"the-page-doesn-t-contain-any-tracks","errorCode":null,"errorMessage":"The page doesn't contain any tracks","messagePattern":"The page doesn't contain any tracks","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/bandcamp.py","lineNumber":303,"sourceCode":"            'description': 'md5:b3cf845ee41b2b1141dc7bde9237255f',\n        },\n        'playlist_count': 2,\n    }]\n\n    @classmethod\n    def suitable(cls, url):\n        return (False\n                if BandcampWeeklyIE.suitable(url) or BandcampIE.suitable(url)\n                else super(BandcampAlbumIE, cls).suitable(url))\n\n    def _real_extract(self, url):\n        uploader_id, album_id = re.match(self._VALID_URL, url).groups()\n        playlist_id = album_id or uploader_id\n        webpage = self._download_webpage(url, playlist_id)\n        tralbum = self._extract_data_attr(webpage, playlist_id)\n        track_info = tralbum.get('trackinfo')\n        if not track_info:\n            raise ExtractorError('The page doesn\\'t contain any tracks')\n        # Only tracks with duration info have songs\n        entries = [\n            self.url_result(\n                urljoin(url, t['title_link']), BandcampIE.ie_key(),\n                str_or_none(t.get('track_id') or t.get('id')), t.get('title'))\n            for t in track_info\n            if t.get('duration')]\n\n        current = tralbum.get('current') or {}\n\n        return {\n            '_type': 'playlist',\n            'uploader_id': uploader_id,\n            'id': playlist_id,\n            'title': current.get('title'),\n            'description': current.get('about'),\n            'entries': entries,\n        }","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/bandcamp.py#L285-L321","documentation":"Raised by BandcampAlbumIE._real_extract when the embedded 'tralbum' JSON blob (read from the page's data attribute) has no 'trackinfo' key or an empty/null trackinfo list. The extractor treats a bandcamp album or discography page as a playlist of tracks; if the embedded metadata carries no track entries there is nothing to return, so it fails with this ExtractorError instead of returning an empty playlist.","triggerScenarios":"Extracting a Bandcamp URL whose _VALID_URL matched (album_id or uploader_id) but whose page's data-tralbum attribute contains trackinfo that is missing, null, or [] — e.g. an artist/discography landing page with no playable album embedded, a track-only page that leaked through suitable(), or a page layout change that moved the tralbum JSON so _extract_data_attr pulls an empty object.","commonSituations":"Passing a bandcamp artist homepage instead of a specific album URL; Bandcamp A/B testing or redesign moving the embedded tralbum payload; pages region-locked or behind an age/country interstitial that lacks trackinfo; a band whose album has no streaming tracks (merch-only page).","solutions":["Confirm the URL points to a real album (contains '/album/') rather than an artist or discography root page.","View page source and check the data-tralbum (or equivalent) attribute actually contains a populated trackinfo array for that URL.","If trackinfo exists but all entries lack 'duration', note the extractor filters those out; a fully filtered list still passes this check, so verify at least one track has duration in the raw JSON.","If the attribute name/schema changed, update _extract_data_attr usage in bandcamp.py:303 to the new embed location."],"exampleFix":"// before\ntralbum = self._extract_data_attr(webpage, playlist_id)\ntrack_info = tralbum.get('trackinfo')\nif not track_info:\n    raise ExtractorError('The page doesn\\'t contain any tracks')\n\n// after: distinguish 'no data at all' from 'data present but empty', which aids debugging\ntralbum = self._extract_data_attr(webpage, playlist_id)\ntrack_info = tralbum.get('trackinfo')\nif not track_info:\n    raise ExtractorError('The page doesn\\'t contain any tracks' if tralbum else 'Unable to extract album data from page', expected=True)","handlingStrategy":"validation","validationCode":"import json, re, requests\n\ndef bandcamp_page_has_tracks(url):\n    html = requests.get(url).text\n    m = re.search(r'data-tralbum=\"([^\"]+)\"', html)\n    if not m:\n        return False\n    tralbum = json.loads(m.group(1).replace('&quot;', '\"'))\n    return bool(tralbum.get('trackinfo'))","typeGuard":"def has_playable_tracks(tralbum):\n    return (\n        isinstance(tralbum, dict)\n        and isinstance(tralbum.get('trackinfo'), list)\n        and any(t.get('duration') for t in tralbum['trackinfo'])\n    )","tryCatchPattern":"try:\n    ydl.extract_info(bc_url)\nexcept ExtractorError as e:\n    if \"doesn't contain any tracks\" in str(e):\n        # artist/merch page or layout change; not transient - do not retry\n        log.skip(bc_url)\n    else:\n        raise","preventionTips":["Only feed /album/ URLs to the album extractor; artist root pages legitimately have no trackinfo.","Pre-fetch the page and check the data-tralbum attribute before extraction in batch pipelines.","Remember tracks without 'duration' are filtered out later — verify at least one timed track exists."],"tags":["bandcamp","playlist","embedded-json","extractor","empty-result"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}