{"record":{"id":"993e60ce34d17c4c","repo":"binary-husky/gpt_academic","slug":"doc2x-conversion-timeout-after-maximum-attempts","errorCode":null,"errorMessage":"Doc2x conversion timeout after maximum attempts","messagePattern":"Doc2x conversion timeout after maximum attempts","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"crazy_functions/pdf_fns/parse_pdf_via_doc2x.py","lineNumber":170,"sourceCode":"    max_attempts = 36\n    attempt = 0\n    while attempt < max_attempts:\n        res = make_request(\n            \"GET\",\n            \"https://v2.doc2x.noedgeai.com/api/v2/convert/parse/result\",\n            headers={\"Authorization\": \"Bearer \" + doc2x_api_key},\n            params=params,\n            timeout=15,\n        )\n        res_data = doc2x_api_response_status(res, uid=f\"uid: {uuid}\")\n        if res_data[\"status\"] == \"success\":\n            break\n        elif res_data[\"status\"] == \"processing\":\n            time.sleep(3)\n            logger.info(\"Doc2x still processing to convert file\")\n            attempt += 1\n    if attempt >= max_attempts:\n        raise RuntimeError(\"Doc2x conversion timeout after maximum attempts\")\n\n    # < ------ 第5步：最后的处理 ------ >\n    logger.info(\"Doc2x 第5步：下载转换后的文件\")\n\n    if format == \"tex\":\n        target_path = latex_dir\n    if format == \"md\":\n        target_path = markdown_dir\n    os.makedirs(target_path, exist_ok=True)\n\n    max_attempt = 3\n    # < ------ 下载 ------ >\n    for attempt in range(max_attempt):\n        try:\n            result_url = res_data[\"url\"]\n            res = make_request(\"GET\", result_url, timeout=60)\n            zip_path = os.path.join(target_path, gen_time_str() + \".zip\")\n            unzip_path = os.path.join(target_path, gen_time_str())","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/crazy_functions/pdf_fns/parse_pdf_via_doc2x.py#L152-L188","documentation":"The second polling loop (step 4, convert-status) gives up when the convert job still reports 'processing' after max_attempts polls at 3-second intervals. Note the asymmetry with error 77: unlike the parse loop, the 'else' branch is absent here — an unexpected status silently falls through and can loop until this timeout instead of raising error 76's counterpart.","triggerScenarios":"Converting a large parsed document to tex/md takes longer than max_attempts × 3s; Doc2x conversion queue backlog; very formula-dense documents converting slowly.","commonSituations":"Same shape as 77 but at the convert stage; large documents, server load; also triggered when an unhandled failure status causes the loop to exhaust attempts without a clear error.","solutions":["Raise max_attempts for the convert loop (it is a separate budget from the parse loop)","Retry the conversion — if the parse succeeded, reusing the uid usually resumes quickly","Reduce output size: convert to 'md' instead of 'tex' if formulas are not needed","Add an explicit else-branch raising on unknown statuses so real failures surface immediately instead of as this timeout"],"exampleFix":"# before\nif res_data[\"status\"] == \"success\":\n    break\nelif res_data[\"status\"] == \"processing\":\n    time.sleep(3); attempt += 1\n\n# after\nif res_data[\"status\"] == \"success\":\n    break\nelif res_data[\"status\"] == \"processing\":\n    time.sleep(3); attempt += 1\nelse:\n    raise RuntimeError(f\"Doc2x convert failed: {res_data}\")","handlingStrategy":"retry","validationCode":"if res_data['status'] not in ('success', 'processing'):\n    raise RuntimeError(f\"Unexpected convert status: {res_data['status']}\")  # fail fast, do not burn attempts","typeGuard":null,"tryCatchPattern":"try:\n    wait_for_conversion(uuid)\nexcept RuntimeError as e:\n    if 'conversion timeout' in str(e):\n        time.sleep(30)\n        wait_for_conversion(uuid, max_attempts=60)\n    else:\n        raise","preventionTips":["Add an explicit else-branch in the poll loop to raise on unknown statuses immediately","Give the convert loop its own, larger attempt budget","Retry conversion by reusing the parse uid instead of re-uploading the file"],"tags":["doc2x","timeout","polling","conversion","large-files"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}