{"record":{"id":"6118db2beef70246","repo":"binary-husky/gpt_academic","slug":"doc2x-processing-timeout-after-maximum-attempts","errorCode":null,"errorMessage":"Doc2x processing timeout after maximum attempts","messagePattern":"Doc2x processing timeout after maximum attempts","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"crazy_functions/pdf_fns/parse_pdf_via_doc2x.py","lineNumber":130,"sourceCode":"    while attempt < max_attempts:\n        res = make_request(\n            \"GET\",\n            \"https://v2.doc2x.noedgeai.com/api/v2/parse/status\",\n            headers={\"Authorization\": \"Bearer \" + doc2x_api_key},\n            params=params,\n            timeout=15,\n        )\n        res_data = doc2x_api_response_status(res)\n        if res_data[\"status\"] == \"success\":\n            break\n        elif res_data[\"status\"] == \"processing\":\n            time.sleep(5)\n            logger.info(f\"Doc2x is processing at {res_data['progress']}%\")\n            attempt += 1\n        else:\n            raise RuntimeError(f\"Doc2x return an error: {res_data}\")\n    if attempt >= max_attempts:\n        raise RuntimeError(\"Doc2x processing timeout after maximum attempts\")\n\n    # < ------ 第3步：提交转化 ------ >\n    logger.info(\"Doc2x 第3步：提交转化\")\n    data = {\n        \"uid\": uuid,\n        \"to\": format,\n        \"formula_mode\": \"dollar\",\n        \"filename\": \"output\"\n    }\n    res = make_request(\n        \"POST\",\n        \"https://v2.doc2x.noedgeai.com/api/v2/convert/parse\",\n        headers={\"Authorization\": \"Bearer \" + doc2x_api_key},\n        json=data,\n        timeout=15,\n    )\n    doc2x_api_response_status(res, uid=f\"uid: {uuid}\")\n","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/crazy_functions/pdf_fns/parse_pdf_via_doc2x.py#L112-L148","documentation":"The parse-status polling loop slept 5s between polls and incremented attempt each 'processing' response; after max_attempts polls still reporting 'processing', it gives up with this timeout. Doc2x did not finish parsing the document within the client's polling budget (max_attempts × 5 seconds).","triggerScenarios":"Large PDFs (hundreds of pages) that take minutes to parse; Doc2x under heavy load; max_attempts left at default (too small); network latency stretching each poll cycle.","commonSituations":"Parsing full academic theses or books; free-tier queues; the job may actually still be running server-side — the client just stopped asking.","solutions":["Increase max_attempts (or the sleep interval) for large documents — e.g. budget 1 attempt per 10 pages","Retry: the job often completes shortly after; Doc2x may reuse the upload via the same uid","Split the PDF into smaller parts and parse each separately","Check Doc2x status page for ongoing degradation before retrying"],"exampleFix":"# before\nmax_attempts = 30  # gives up too early on big files\n\n# after\nmax_attempts = max(30, estimated_pages // 5)  # scale budget with document size","handlingStrategy":"retry","validationCode":"from pypdf import PdfReader\npages = len(PdfReader(pdf_path).pages)\nmax_attempts = max(30, pages // 5)  # budget scales with document size","typeGuard":null,"tryCatchPattern":"try:\n    wait_for_parse(uuid)\nexcept RuntimeError as e:\n    if 'processing timeout' in str(e):\n        time.sleep(30)\n        wait_for_parse(uuid, max_attempts=60)  # job usually still running server-side; extend budget\n    else:\n        raise","preventionTips":["Scale the polling budget with the PDF page count","On timeout, poll once more after a delay before restarting the whole upload","Log per-poll progress percentage to distinguish slow progress from a hung job"],"tags":["doc2x","timeout","polling","large-files"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}