yt-dlp/yt-dlp · error · ExtractorError
Unknown GraphQL API error
Error message
Unknown GraphQL API error
What it means
Thrown by TelewebionIE._call_graphql_api when the POST to https://graph.telewebion.ir/graphql returns a falsy body or a body containing an 'errors' array. Message text is joined from errors[*].message; if the errors carry no string messages (or the result is empty), the fallback message 'Unknown GraphQL API error' is raised. This is the GraphQL-standard error envelope surfaced as an ExtractorError.
Source
Thrown at yt_dlp/extractor/telewebion.py:82
variables: dict[str, tuple[str, str]] | None = None,
note='Downloading GraphQL JSON metadata',
):
parameters = ''
if variables:
parameters = ', '.join(f'${name}: {type_}' for name, (type_, _) in variables.items())
parameters = f'({parameters})'
result = self._download_json('https://graph.telewebion.ir/graphql', video_id, note, data=json.dumps({
'operationName': operation,
'query': f'query {operation}{parameters} @cacheControl(maxAge: 60) {{{query}\n}}\n',
'variables': {name: value for name, (_, value) in (variables or {}).items()},
}, separators=(',', ':')).encode(), headers={
'Content-Type': 'application/json',
'Accept': 'application/json',
})
if not result or traverse_obj(result, 'errors'):
message = ', '.join(traverse_obj(result, ('errors', ..., 'message', {str})))
raise ExtractorError(message or 'Unknown GraphQL API error')
return result['data']
def _real_extract(self, url):
video_id = self._match_id(url)
if not video_id.startswith('0x'):
video_id = hex(int(video_id))
episode_data = self._call_graphql_api('getEpisodeDetail', video_id, textwrap.dedent('''
queryEpisode(filter: {EpisodeID: $EpisodeId}, first: 1) {
title
program {
ProgramID
title
}
image
view_count
durationView on GitHub (pinned to 81ecd58b13)
Solutions
- Read the joined error messages — Telewebion's API usually states the exact reason (e.g. episode not found).
- Verify the episode still exists at telewebion.ir in a browser; if removed, the id is permanently dead.
- Update yt-dlp in case the GraphQL query shape was updated to match a schema change.
- If throttling is suspected, slow down and retry later from a non-rate-limited network.
Defensive patterns
Strategy: try-catch
Type guard
def is_graphql_error(e: Exception) -> bool:
return isinstance(e, ExtractorError) and ('GraphQL' in str(e) or 'telewebion' in str(e).lower()) Try / catch
try:
ydl.extract_info(url)
except ExtractorError as e:
msg = str(e)
if 'Unknown GraphQL API error' in msg or 'episode' in msg.lower():
log.info('telewebion API rejected the request: %s', msg)
else:
raise Prevention
- Validate episode links in a browser before batch archiving — reindexed ids fail permanently.
- Log the joined GraphQL messages; they usually name the exact server-side reason.
- Throttle requests to graph.telewebion.ir to avoid throttle-driven error envelopes.
When it happens
Trigger: Any GraphQL operation (getEpisodeDetail etc.) failing server-side: unknown/deleted episode id passed as $EpisodeId, invalid query shape after the site changed its schema, rate limiting, or an empty 200 response. traverse_obj(result, 'errors') truthy OR result falsy both land here.
Common situations: Episode ids from old links after Telewebion re-indexed content (the extractor converts decimal ids to hex — a stale id maps to nothing); schema changes on the GraphQL endpoint; IP-based throttling of the graph host.
Related errors
- GraphQL API error: {errors or "Unknown error"}
- Unable to load data. Error code: {code}
- Unable to download video %s
- Iwara API said: {error or "nothing"}
- Iwara says: {errmsg}
AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22).
Data as JSON: /api/errors/6f90c522305bc723.
Report an issue: GitHub.