{"record":{"id":"76d00d887923e27b","repo":"soimort/you-get","slug":"failed","errorCode":null,"errorMessage":"Failed","messagePattern":"Failed","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/you_get/extractors/icourses.py","lineNumber":39,"sourceCode":"        raise Exception('You can download it with -l flag')\n    icourses_parser = ICousesExactor(url=url)\n    icourses_parser.basic_extract()\n    title = icourses_parser.title\n    size = None\n    for i in range(5):\n        try:\n            # use this url only for size\n            size_url = icourses_parser.generate_url(0)\n            _, type_, size = url_info(size_url, headers=fake_headers)\n        except error.HTTPError:\n            logging.warning('Failed to fetch the video file! Retrying...')\n            sleep(random.Random().randint(2, 5))  # Prevent from blockage\n        else:\n            print_info(site_info, title, type_, size)\n            break\n\n    if size is None:\n        raise Exception(\"Failed\")\n\n    if not kwargs['info_only']:\n        real_url = icourses_parser.update_url(0)\n        headers = fake_headers.copy()\n        headers['Referer'] = url\n        download_urls_icourses(real_url, title, 'flv',total_size=size, output_dir=output_dir, max_size=15728640, dyn_callback=icourses_parser.update_url)\n    return\n\n\ndef get_course_title(url, course_type, page=None):\n    if page is None:\n        try:\n            # shard course page could be gbk but with charset=\"utf-8\"\n            page = get_content(url, decoded=False).decode('gbk')\n        except UnicodeDecodeError:\n            page = get_content(url, decoded=False).decode('utf8')\n\n    if course_type == 'shared_old':","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/soimort/you-get/blob/049548f3f3f35e67ba8d3181c71fdc71d11cf260/src/you_get/extractors/icourses.py#L21-L57","documentation":"Raised as plain Exception in icourses_download (src/you_get/extractors/icourses.py:39). The code tries up to 5 times to probe the generated video URL with url_info() to learn the file size; if every attempt raises urllib's HTTPError (logged as 'Failed to fetch the video file! Retrying...'), size stays None and the download is aborted.","triggerScenarios":"ICousesExactor.generate_url(0) yields a URL that url_info() rejects with HTTPError on 5 consecutive attempts: the icourses server blocks/throttles the request (the code sleeps 2-5s between tries specifically to 'prevent blockage'), or the generated URL is invalid (bad uuid/IService flashvars) so the server answers 4xx/5xx every time.","commonSituations":"Aggressive repeated downloads getting rate-limited/blocked by icourses.cn; expired or wrongly parsed player tokens producing dead URLs; site-side changes to the video API.","solutions":["Wait several minutes and retry — the failure mode is usually temporary blocking.","Verify the generated size_url in a browser/curl; a persistent 4xx means the URL construction (flashvars parsing) is broken — upgrade you-get or fix ICousesExactor.","Reduce request frequency in scripts (honor the existing randomized sleeps) to avoid tripping the block."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"import time\nfor attempt in range(3):\n    try:\n        icourses_download(url, output_dir)\n        break\n    except Exception as e:\n        if str(e) == 'Failed':\n            time.sleep(300)  # let the server-side block cool down\n            continue\n        raise","preventionTips":["Space icourses requests minutes apart; the extractor already random-sleeps to dodge blocks.","Failures after the built-in 5 retries mean a hard block or dead URL — stop, don't hammer."],"tags":["you-get","icourses","rate-limit","retry-exhausted","network"],"backgroundTag":null,"analyzedSha":"049548f3f3f35e67ba8d3181c71fdc71d11cf260","analyzedAt":"2026-08-15T03:58:15.069Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}