{"record":{"id":"742eceeb6d7ddbf2","repo":"soimort/you-get","slug":"api-returned-fail","errorCode":null,"errorMessage":"API returned fail","messagePattern":"API returned fail","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/you_get/extractors/icourses.py","lineNumber":226,"sourceCode":"        if hit is None:\n            raise Exception('Cannot find flashvars')\n        flashvar_str = hit.group(1)\n\n        uuid = re.search(r'uuid\\s*:\\s*\\\"?(\\w+)\\\"?', flashvar_str).group(1)\n        other = re.search(r'other\\s*:\\s*\"(.*?)\"', flashvar_str).group(1)\n        isvc = re.search(r'IService\\s*:\\s*\\'(.+?)\\'', flashvar_str).group(1)\n\n        player_time_patt = r'MPlayer.swf\\?v\\=(\\d+)'\n        player_time = re.search(player_time_patt, self.page).group(1)\n\n        self.flashvars = dict(IService=isvc, uuid=uuid, other=other, v=player_time)\n\n    def api_req(self, url):\n        xml_str = get_content(url)\n        dom = parseString(xml_str)\n        status = dom.getElementsByTagName('result')[0].getAttribute('status')\n        if status != 'success':\n            raise Exception('API returned fail')\n\n        api_res = {}\n        meta = dom.getElementsByTagName('metadata')\n        for m in meta:\n            key = m.getAttribute('name')\n            val = m.firstChild.nodeValue\n            api_res[key] = val\n        self.api_data = api_res\n\n    def basic_extract(self):\n        self.get_title()\n        self.get_flashvars()\n        api_req_url = '{}?{}'.format(self.flashvars['IService'], parse.urlencode(self.flashvars))\n        self.api_req(api_req_url)\n\n    def do_extract(self, received=0):\n        self.basic_extract()\n        return self.generate_url(received)","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/soimort/you-get/blob/049548f3f3f35e67ba8d3181c71fdc71d11cf260/src/you_get/extractors/icourses.py#L208-L244","documentation":"Raised as plain Exception in ICousesExactor.api_req (src/you_get/extractors/icourses.py:226). The player's XML API is queried for stream metadata; the <result> element's status attribute must be 'success'. Anything else (error, denied) aborts extraction.","triggerScenarios":"api_req() fetches an API URL built from flashvars (IService endpoint with uuid/other), parses it with minidom, and dom.getElementsByTagName('result')[0].getAttribute('status') != 'success'. Happens when uuid/other tokens are stale or wrongly parsed, the API rejects the request, or icourses changed the response schema (also fails with IndexError if <result> disappears).","commonSituations":"Expired per-session tokens reused by long-running scripts; flashvars parsing producing truncated values; API contract change after site maintenance.","solutions":["Re-fetch the video page fresh each run so flashvars-derived tokens are current — never cache IService/uuid/other across sessions.","Log xml_str to see the actual status/error the API returns and adjust the request accordingly.","If the XML schema changed, update api_req's parsing (or upgrade you-get)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    icourses_download(url, output_dir)\nexcept Exception as e:\n    if str(e) == 'API returned fail':\n        icourses_download(url, output_dir)  # exactly once: refresh page -> new tokens\n    else:\n        raise","preventionTips":["Always fetch the video page fresh so flashvars tokens (uuid/other/IService) are current.","Log the API XML body when status != success to distinguish token expiry from schema change."],"tags":["you-get","icourses","api-error","parse-error","extractor"],"backgroundTag":null,"analyzedSha":"049548f3f3f35e67ba8d3181c71fdc71d11cf260","analyzedAt":"2026-08-15T03:58:15.069Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}