ytdl-org/youtube-dl · error · ExtractorError
%s returns error %d
Error message
%s returns error %d
What it means
The second branch of BiliBiliBangumiIE._report_error: the API result dict has no 'message' key but does have a 'code' key, so the error reports the numeric code ('%s returns error %d'). Expected=True. This branch typically fires when the API signals failure with only a status code and no human-readable text.
Source
Thrown at youtube_dl/extractor/bilibili.py:119
},
'params': {
'skip_download': True, # Test metadata only
},
}]
}, {
# new BV video id format
'url': 'https://www.bilibili.com/video/BV1JE411F741',
'only_matching': True,
}]
_APP_KEY = 'iVGUTjsxvpLeuDCf'
_BILIBILI_KEY = 'aHRmhWMLkdeMuILqORnYZocwMBpMEOdt'
def _report_error(self, result):
if 'message' in result:
raise ExtractorError('%s said: %s' % (self.IE_NAME, result['message']), expected=True)
elif 'code' in result:
raise ExtractorError('%s returns error %d' % (self.IE_NAME, result['code']), expected=True)
else:
raise ExtractorError('Can\'t extract Bangumi episode ID')
def _real_extract(self, url):
url, smuggled_data = unsmuggle_url(url, {})
mobj = re.match(self._VALID_URL, url)
video_id = mobj.group('id') or mobj.group('id_bv')
anime_id = mobj.group('anime_id')
webpage = self._download_webpage(url, video_id)
if 'anime/' not in url:
cid = self._search_regex(
r'\bcid(?:["\']:|=)(\d+)', webpage, 'cid',
default=None
) or compat_parse_qs(self._search_regex(
[r'EmbedPlayer\([^)]+,\s*"([^"]+)"\)',
r'EmbedPlayer\([^)]+,\s*\\"([^"]+)\\"\)',View on GitHub (pinned to 956b8c5855)
Solutions
- Map the code: common Bilibili codes are -400 (bad request), -404 (not found), -799 (rate limit); fix the request accordingly.
- Verify the bangumi id by opening the page in a browser and comparing with the extractor's captured anime/episode id.
- If code arrives as a string in newer API versions, coerce before formatting (%d on a str raises) and report the schema change upstream.
- For rate limiting (-799 style), back off and retry rather than hammering.
Example fix
// before
elif 'code' in result:
raise ExtractorError('%s returns error %d' % (self.IE_NAME, result['code']), expected=True)
// after: tolerate string codes and show them safely
elif 'code' in result:
code = result['code']
raise ExtractorError('%s returns error %s' % (self.IE_NAME, code), expected=True) Defensive patterns
Strategy: try-catch
Try / catch
try:
ydl.extract_info(bangumi_url)
except ExtractorError as e:
m = re.search(r'returns error (-?\d+)', str(e))
if m:
code = int(m.group(1))
if code in (-799,): # rate limit style
backoff_and_retry(bangumi_url)
elif code == -404:
mark_not_found(bangumi_url)
else:
raise Prevention
- Map Bilibili numeric codes (-400 bad request, -404 not found, rate-limit codes) to concrete handling.
- Throttle request rates to Bilibili to avoid code-based rate-limit responses.
- Watch for string codes (would crash %d) — a sign the API schema changed.
When it happens
Trigger: A Bangumi API response shaped like {'code': -404, ...} or {'code': <negative/nonzero>} without a message — unknown season/episode ids, expired signed URLs, or API versions that omit the message field. The %d format also implies code must be an integer; a string code would raise a format error instead.
Common situations: Wrong anime_id/episode_id parsed from the URL; API contract change dropping the message field; signed-request staleness; bangumi entries delisted with bare error codes.
Related errors
- %s said: %s
- Can't extract Bangumi episode ID
- Letv cloud returned error %d
- Bigo says: %s (code %s)
- %s said: %s
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/4fd8024d1ca76723.
Report an issue: GitHub.