{"record":{"id":"8ba551ec87e26b58","repo":"ytdl-org/youtube-dl","slug":"s-encountered-an-error-s","errorCode":null,"errorMessage":"%s encountered an error: %s","messagePattern":"(.+?) encountered an error: (.+?)","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/mgoon.py","lineNumber":50,"sourceCode":"        },\n        {\n            'url': 'http://www.mgoon.com/play/view/5582148',\n            'only_matching': True,\n        },\n        {\n            'url': 'http://video.mgoon.com/5582148',\n            'only_matching': True,\n        },\n    ]\n\n    def _real_extract(self, url):\n        mobj = re.match(self._VALID_URL, url)\n        video_id = mobj.group('id')\n\n        data = self._download_json(self._API_URL.format(video_id), video_id)\n\n        if data.get('errorInfo', {}).get('code') != 'NONE':\n            raise ExtractorError('%s encountered an error: %s' % (\n                self.IE_NAME, data['errorInfo']['message']), expected=True)\n\n        v_info = data['videoInfo']\n        title = v_info.get('v_title')\n        thumbnail = v_info.get('v_thumbnail')\n        duration = v_info.get('v_duration')\n        upload_date = unified_strdate(v_info.get('v_reg_date'))\n        uploader_id = data.get('userInfo', {}).get('u_alias')\n        if duration:\n            duration /= 1000.0\n\n        age_limit = None\n        if data.get('accessInfo', {}).get('code') == 'VIDEO_STATUS_ADULT':\n            age_limit = 18\n\n        formats = []\n        get_quality = qualities(['360p', '480p', '720p', '1080p'])\n        for fmt in data['videoFiles']:","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/mgoon.py#L32-L68","documentation":"Raised by the mgoon extractor when the video API response's errorInfo.code is anything other than 'NONE' — the service's own error channel. The message embeds errorInfo.message verbatim. Expected=True, so it represents a normal service refusal (removed video, permission, quota) rather than a parsing bug.","triggerScenarios":"GET of self._API_URL.format(video_id) returns JSON where data['errorInfo']['code'] != 'NONE'; the raise reads data['errorInfo']['message'] directly (KeyError if the service omits it).","commonSituations":"Video deleted from mgoon; API requiring a referer/session for some assets; the (now largely defunct) Korean service returning generic error codes for all requests; schema change dropping the message field and turning the intended error into a KeyError.","solutions":["Read the embedded message — it is mgoon's own reason text.","Confirm the video still exists at http://video.mgoon.com/{id}.","Update youtube-dl; the mgoon extractor and its API endpoint have needed maintenance as the site wound down.","If the whole service is offline, obtain the media from another source; no client fix recovers it."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def mgoon_has_error(data):\n    return isinstance(data, dict) and data.get('errorInfo', {}).get('code') != 'NONE'","tryCatchPattern":"try:\n    info = ydl.extract_info(url, download=False)\nexcept ExtractorError as e:\n    if 'mgoon encountered an error' in str(e):\n        mark_permanently_dead(url)  # service-side refusal; not retryable\n    else:\n        raise","preventionTips":["Check mgoon.com availability in a browser before queueing (service is largely defunct).","Log the embedded errorInfo message for triage instead of retrying."],"tags":["api-response","service-error","expected-error"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}