{"record":{"id":"22d0d0ea6bd8741b","repo":"binary-husky/gpt_academic","slug":"doc2x-return-an-error-res-json","errorCode":null,"errorMessage":"Doc2x return an error: {res.json()}","messagePattern":"Doc2x return an error: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"crazy_functions/pdf_fns/parse_pdf_via_doc2x.py","lineNumber":193,"sourceCode":"    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())\n            if res.status_code == 200:\n                with open(zip_path, \"wb\") as f:\n                    f.write(res.content)\n            else:\n                raise RuntimeError(f\"Doc2x return an error: {res.json()}\")\n        except Exception as e:\n            if attempt < max_attempt - 1:\n                logger.error(f\"Failed to download uid = {uuid} file, retrying... {e}\")\n                time.sleep(3)\n                continue\n            else:\n                raise e\n\n    # < ------ 解压 ------ >\n    import zipfile\n    with zipfile.ZipFile(zip_path, \"r\") as zip_ref:\n        zip_ref.extractall(unzip_path)\n    return zip_path, unzip_path\n\n\ndef 解析PDF_DOC2X_单文件(\n    fp,\n    project_folder,","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/crazy_functions/pdf_fns/parse_pdf_via_doc2x.py#L175-L211","documentation":"During file download (step 5), the GET to the result URL returned a non-200 status, so the client raises with res.json() embedded. The surrounding loop retries up to 3 times with a 3s backoff, re-raising the last error only after all attempts fail. Non-200 on a presigned result URL typically means the URL expired or the download service is flaky.","triggerScenarios":"Presigned download URL expired because polling took too long (see 77/78); transient CDN/origin 5xx; res.json() itself raising if the error body is not JSON (which would surface as a JSONDecodeError instead of this message); network proxy mangling the request.","commonSituations":"See trigger scenarios.","solutions":["Retries are built in (3 attempts) — persistent failure means the URL expired; re-run the whole flow to get a fresh URL","Reduce delay between convert-success and download so the presigned URL does not expire","If res.json() raised, capture res.text instead for non-JSON error bodies","Check network/proxy egress to the download host"],"exampleFix":"# before\nraise RuntimeError(f\"Doc2x return an error: {res.json()}\")\n\n# after\nraise RuntimeError(f\"Doc2x download error {res.status_code}: {res.text[:500]}\")","handlingStrategy":"retry","validationCode":"if res.status_code != 200:\n    # do not blindly res.json() — error bodies may not be JSON\n    raise RuntimeError(f\"download {res.status_code}: {res.text[:200]}\")","typeGuard":null,"tryCatchPattern":"for attempt in range(3):\n    try:\n        download_result(url)\n        break\n    except RuntimeError as e:\n        if attempt == 2 or 'expired' in str(e).lower():\n            restart_full_doc2x_flow(pdf_path)  # expired presigned URL needs a fresh one\n        time.sleep(3)","preventionTips":["Download immediately after convert-success so the presigned URL cannot expire","Read res.text, not res.json(), on non-200 bodies","If built-in 3 retries fail, restart from upload — a fresh URL is the only cure for expiry"],"tags":["doc2x","download","presigned-url","retry","http-status"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}