ytdl-org/youtube-dl · error · ExtractorError
said
Error message
%s said: %s
What it means
Raised by the HRTi (Croatian Radiotelevision) extractor during _login when the authentication endpoint response contains an error.message field. The message from HRTi's auth API (e.g. invalid credentials, expired token) is forwarded verbatim prefixed with the extractor name.
Solutions
- Check the HRTi username/password used for authentication (netrc or --username/--password).
- Confirm the account still works by logging in on the HRTi website.
- Update youtube-dl/yt-dlp in case the login API contract changed.
Defensive patterns
Strategy: try-catch
Try / catch
try:
ydl.extract_info(hrti_url)
except ExtractorError as e:
if str(e).startswith('hrti said:'):
# auth-side rejection: verify credentials, then give up for this run
raise AuthRejected(str(e)) Prevention
- Store HRTi credentials in netrc instead of CLI to avoid truncation issues.
- Test credentials on the HRTi site before batch runs.
- Distinguish login errors from extraction errors by the 'IE said:' prefix.
When it happens
Trigger: Calling an HRTi URL that triggers _real_initialize -> _login, where the POST to self._login_url returns a JSON body with a non-empty 'error'.'message' (bad username/password, or device authorization failure).
Common situations: Wrong or expired HRTi credentials supplied via netrc/CLI, password changes on the account, or API-side changes in HRTi's login flow.
Related errors
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/de7c81513846e57b.
Report an issue: GitHub.
Appendix: source
Thrown at youtube_dl/extractor/hrti.py:91
auth_data = {
'username': username,
'password': password,
}
try:
auth_info = self._download_json(
self._login_url, None, note='Logging in', errnote='Unable to log in',
data=json.dumps(auth_data).encode('utf-8'))
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 406:
auth_info = self._parse_json(e.cause.read().encode('utf-8'), None)
else:
raise
error_message = auth_info.get('error', {}).get('message')
if error_message:
raise ExtractorError(
'%s said: %s' % (self.IE_NAME, error_message),
expected=True)
self._token = auth_info['secure_streaming_token']
def _real_initialize(self):
self._initialize_api()
self._login()
class HRTiIE(HRTiBaseIE):
_VALID_URL = r'''(?x)
(?:
hrti:(?P<short_id>[0-9]+)|
https?://
hrti\.hrt\.hr/(?:\#/)?video/show/(?P<id>[0-9]+)/(?P<display_id>[^/]+)?
)
'''View on GitHub (pinned to 956b8c5855)