{"record":{"id":"c48495a5fe61f560","repo":"ytdl-org/youtube-dl","slug":"stream-s-is-upcoming","errorCode":null,"errorMessage":"Stream %s is upcoming","messagePattern":"Stream (.+?) is upcoming","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"warning","filePath":"youtube_dl/extractor/freshlive.py","lineNumber":52,"sourceCode":"    }\n\n    def _real_extract(self, url):\n        video_id = self._match_id(url)\n\n        webpage = self._download_webpage(url, video_id)\n\n        options = self._parse_json(\n            self._search_regex(\n                r'window\\.__CONTEXT__\\s*=\\s*({.+?});\\s*</script>',\n                webpage, 'initial context'),\n            video_id)\n\n        info = options['context']['dispatcher']['stores']['ProgramStore']['programs'][video_id]\n\n        title = info['title']\n\n        if info.get('status') == 'upcoming':\n            raise ExtractorError('Stream %s is upcoming' % video_id, expected=True)\n\n        stream_url = info.get('liveStreamUrl') or info['archiveStreamUrl']\n\n        is_live = info.get('liveStreamUrl') is not None\n\n        formats = self._extract_m3u8_formats(\n            stream_url, video_id, 'mp4',\n            'm3u8_native', m3u8_id='hls')\n\n        if is_live:\n            title = self._live_title(title)\n\n        return {\n            'id': video_id,\n            'formats': formats,\n            'title': title,\n            'description': info.get('description'),\n            'thumbnail': info.get('thumbnailUrl'),","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/freshlive.py#L34-L70","documentation":"Raised by the FreshLive extractor when the program info embedded in window.__CONTEXT__ has status 'upcoming', meaning the stream has been announced but has not started yet. It is expected=True and simply tells the caller to wait: no stream URL exists for extraction until the broadcast begins.","triggerScenarios":"options['context']['dispatcher']['stores']['ProgramStore']['programs'][video_id] has status == 'upcoming' before liveStreamUrl/archiveStreamUrl are consulted. Triggered by opening a scheduled FreshLive stream page before its start time.","commonSituations":"Users queuing downloads ahead of announced streams; reminder-bots hitting the page early; timezone confusion about the broadcast start.","solutions":["Wait until the stream is live (or has ended and an archiveStreamUrl exists), then retry","Schedule the download for after the announced start time plus a margin","Note freshlive.jp (now FreshLive) service changes; verify the platform still operates this content","Update yt-dlp in case the __CONTEXT__ payload structure changed"],"exampleFix":"# before\nyoutube_dl 'https://freshlive.jp/xx/123456'  # 2 hours before start\n# ERROR: Stream 123456 is upcoming\n\n# after\n# wait until broadcast starts, then\nyt-dlp 'https://freshlive.jp/xx/123456'","handlingStrategy":"retry","validationCode":"# Parse the embedded context to check stream status first\nimport re, json\nm = re.search(r'window\\.__CONTEXT__\\s*=\\s*({.+?});\\s*</script>', webpage)\nctx = json.loads(m.group(1))\nstatus = ctx['context']['dispatcher']['stores']['ProgramStore']['programs'][vid]['status']\nif status == 'upcoming':\n    schedule_retry(announced_start_time + margin)","typeGuard":null,"tryCatchPattern":"try:\n    ydl.extract_info(url)\nexcept ExtractorError as e:\n    if 'is upcoming' in str(e):\n        schedule_retry_at_stream_start(url)","preventionTips":["Schedule downloads after the announced broadcast start time","Treat 'upcoming' as a retryable state with backoff, unlike permanent unavailability"],"tags":["freshlive","extractor","upcoming","live"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}