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
              duration

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Read the joined error messages — Telewebion's API usually states the exact reason (e.g. episode not found).
  2. Verify the episode still exists at telewebion.ir in a browser; if removed, the id is permanently dead.
  3. Update yt-dlp in case the GraphQL query shape was updated to match a schema change.
  4. 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

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


AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22). Data as JSON: /api/errors/6f90c522305bc723. Report an issue: GitHub.