{"record":{"id":"7de09c1285f8cf90","repo":"ytdl-org/youtube-dl","slug":"s-is-offline-7de09c","errorCode":null,"errorMessage":"%s is offline","messagePattern":"(.+?) is offline","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"warning","filePath":"youtube_dl/extractor/twitch.py","lineNumber":796,"sourceCode":"                    'isVodOrCollection': False,\n                    'vodID': '',\n                },\n            }, {\n                'operationName': 'VideoPreviewOverlay',\n                'variables': {'login': channel_name},\n            }],\n            'Downloading stream GraphQL')\n\n        user = gql[0]['data']['user']\n\n        if not user:\n            raise ExtractorError(\n                '%s does not exist' % channel_name, expected=True)\n\n        stream = user['stream']\n\n        if not stream:\n            raise ExtractorError('%s is offline' % channel_name, expected=True)\n\n        access_token = self._download_access_token(\n            channel_name, 'stream', 'channelName')\n        token = access_token['value']\n\n        stream_id = stream.get('id') or channel_name\n        query = {\n            'allow_source': 'true',\n            'allow_audio_only': 'true',\n            'allow_spectre': 'true',\n            'p': random.randint(1000000, 10000000),\n            'player': 'twitchweb',\n            'playlist_include_framerate': 'true',\n            'segment_preference': '4',\n            'sig': access_token['signature'].encode('utf-8'),\n            'token': token.encode('utf-8'),\n        }\n        formats = self._extract_m3u8_formats(","sourceCodeStart":778,"sourceCodeEnd":814,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/twitch.py#L778-L814","documentation":"Raised by TwitchStreamIE when the channel's user object exists but user.stream is falsy — the channel is simply not broadcasting right now. Expected error; it is a state condition, not a failure to parse.","triggerScenarios":"Extracting any twitch.tv/<name> URL for a channel that is currently offline (user['stream'] null/empty after the existence check passed).","commonSituations":"Trying to download a live stream after it ended, scheduled streams, reruns the API does not expose as stream, timezone mistakes about broadcast schedules.","solutions":["Check the channel page for a LIVE badge; if offline, wait for the broadcast and retry.","Download the VOD afterwards via its /videos/ URL once published.","Use a monitoring script/timer to re-attempt when the stream comes online.","If it is a rerun, try the underlying VOD URL instead."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import requests\nq = [{'operationName': 'StreamMetadata', 'variables': {'login': channel}}]\nr = requests.post('https://gql.twitch.tv/gql', json=q, headers={'Client-ID': CLIENT_ID})\nstream = (r.json()[0]['data'].get('user') or {}).get('stream')\nif not stream:\n    schedule_retry(channel, when='next broadcast window')","typeGuard":"def is_streaming(data: dict) -> bool:\n    return bool((data.get('user') or {}).get('stream'))","tryCatchPattern":"try:\n    ydl.extract_info(channel_url)\nexcept ExtractorError as e:\n    if 'is offline' in str(e):\n        retry_later(channel_url, backoff_minutes=15)  # state, not failure\n    else:\n        raise","preventionTips":["Poll the lightweight stream GraphQL endpoint and start the download when stream becomes non-null.","Treat 'offline' as retryable state; treat 'does not exist' as permanent."],"tags":["twitch","live","offline","transient"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}