ytdl-org/youtube-dl · error · ExtractorError
lynda returned error: %s
Error message
lynda returned error: %s
What it means
Raised by LyndaIE when the single-video API response contains a 'Status' key, which Lynda only includes when the request failed. The message embeds video['Message'], Lynda's own description of the failure (e.g. 'Video not found'). Marked expected=True because it maps a well-formed service error to a user-visible message.
Source
Thrown at youtube_dl/extractor/lynda.py:186
})
self._sort_formats(formats)
conviva = self._download_json(
'https://www.lynda.com/ajax/player/conviva', video_id,
'Downloading conviva JSON', query=query)
return {
'id': video_id,
'title': conviva['VideoTitle'],
'description': conviva.get('VideoDescription'),
'release_year': int_or_none(conviva.get('ReleaseYear')),
'duration': int_or_none(conviva.get('Duration')),
'creator': conviva.get('Author'),
'formats': formats,
}
if 'Status' in video:
raise ExtractorError(
'lynda returned error: %s' % video['Message'], expected=True)
if video.get('HasAccess') is False:
self._raise_unavailable(video_id)
video_id = compat_str(video.get('ID') or video_id)
duration = int_or_none(video.get('DurationInSeconds'))
title = video['Title']
formats = []
fmts = video.get('Formats')
if fmts:
formats.extend([{
'url': f['Url'],
'ext': f.get('Extension'),
'width': int_or_none(f.get('Width')),
'height': int_or_none(f.get('Height')),View on GitHub (pinned to 956b8c5855)
Solutions
- Read the embedded Message text; it states Lynda's reason (most often that the video id does not exist).
- Confirm the video id by opening the lynda.com URL in a browser; if it 404s there, the id is dead.
- Log in with entitled credentials (--username/--password or --cookies) if the video requires a subscription.
- Update youtube-dl in case the video endpoint changed, then retry with -v to capture the raw response.
Defensive patterns
Strategy: try-catch
Type guard
def lynda_video_has_error(video_json):
return isinstance(video_json, dict) and 'Status' in video_json Try / catch
try:
info = ydl.extract_info(url, download=False)
except ExtractorError as e:
if 'lynda returned error' in str(e):
msg = str(e).rsplit(':', 1)[1].strip() # e.g. 'Video not found'
log_skip(url, msg) # treat as dead resource, continue batch
else:
raise Prevention
- Validate video ids against the course listing before downloading individual videos.
- Use entitled credentials so Status-based access refusals cannot occur.
- Treat 'lynda returned error' as a permanent skip, not a retryable failure.
When it happens
Trigger: GET of the lynda.com video REST endpoint returns JSON whose top-level object has a truthy/any 'Status' key; the very next line's HasAccess check is never reached because the raise happens first.
Common situations: Downloading a video id that was removed or unpublished; a course video whose id was scraped from a stale playlist page; an account without entitlement seeing Status-based refusals; API version changes making previously silent errors visible.
Related errors
- %s said: %s
- %s encountered an error: %s
- %s
- %s says: %s (IE_NAME, msg) or 'Video unavailable: no reason
- Invalid url for track %d of album url %s
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/256007097f147075.
Report an issue: GitHub.