{"record":{"id":"bc14cc25856e7ab0","repo":"binary-husky/gpt_academic","slug":"id-paper-id","errorCode":null,"errorMessage":"未找到ID为 {paper_id} 的论文","messagePattern":"未找到ID为 (.+?) 的论文","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"crazy_functions/review_fns/data_sources/arxiv_source.py","lineNumber":309,"sourceCode":"            limit=limit,\n            sort_by=sort_by,\n            sort_order=sort_order\n        )\n\n    async def download_pdf(self, paper_id: str, dirpath: str = \"./\", filename: str = \"\") -> str:\n        \"\"\"下载论文PDF\n\n        Args:\n            paper_id: arXiv ID\n            dirpath: 保存目录\n            filename: 文件名，如果为空则使用默认格式：{paper_id}_{标题}.pdf\n\n        Returns:\n            保存的文件路径\n        \"\"\"\n        papers = await self.search_by_id(paper_id)\n        if not papers:\n            raise ValueError(f\"未找到ID为 {paper_id} 的论文\")\n        paper = papers[0]\n\n        if not filename:\n            # 清理标题中的非法字符\n            safe_title = \"\".join(c if c.isalnum() else \"_\" for c in paper.title)\n            filename = f\"{paper_id}_{safe_title}.pdf\"\n\n        filepath = os.path.join(dirpath, filename)\n        urlretrieve(paper.url, filepath)\n        return filepath\n\n    async def download_source(self, paper_id: str, dirpath: str = \"./\", filename: str = \"\") -> str:\n        \"\"\"下载论文源文件（通常是LaTeX源码）\n\n        Args:\n            paper_id: arXiv ID\n            dirpath: 保存目录\n            filename: 文件名，如果为空则使用默认格式：{paper_id}_{标题}.tar.gz","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/crazy_functions/review_fns/data_sources/arxiv_source.py#L291-L327","documentation":"ArxivSource.download_pdf resolves a paper by calling `await self.search_by_id(paper_id)`; if the search returns an empty list it raises ValueError because there is nothing to download. It does not distinguish 'bad ID' from 'arXiv API returned nothing' — search_by_id returning [] is always treated as ID-not-found.","triggerScenarios":"Passing a malformed arXiv ID ('12345', 'abc', missing version prefix like '2401.00001' vs '2401.00001v1' handled differently), an ID for a withdrawn paper, or a valid ID when the arXiv API call inside search_by_id silently returns no results (network issue parsed as empty).","commonSituations":"User pastes a DOI or URL fragment instead of the bare arXiv ID; ID has whitespace/newline attached; paper was withdrawn or the listing is temporarily unavailable; transient arXiv API flakiness makes search_by_id return [].","solutions":["Normalize the ID before calling: strip whitespace, strip the 'arxiv.org/abs/' prefix, keep formats like '2401.00001' or 'cs/0301012'.","Verify the ID resolves: open https://arxiv.org/abs/<paper_id> in a browser or call search_by_id directly and inspect the result.","If the ID looks valid, retry once — the arXiv API occasionally returns empty results under rate limiting (arxiv package raises/warns on 429).","Handle ValueError at the call site to report 'paper not found' instead of crashing the download pipeline."],"exampleFix":"# before\nawait source.download_pdf('https://arxiv.org/abs/2401.00001', './papers')\n\n# after\nimport re\nraw = 'https://arxiv.org/abs/2401.00001v2'\npaper_id = re.sub(r'.*abs/', '', raw).strip()\npapers = await source.search_by_id(paper_id)\nif not papers:\n    raise ValueError(f'未找到ID为 {paper_id} 的论文')\nawait source.download_pdf(paper_id, './papers')","handlingStrategy":"validation","validationCode":"import re\n\nARXIV_ID = re.compile(r'^(\\d{4}\\.\\d{4,5}|[a-z-]+\\.[A-Z]{2}/\\d{7})(v\\d+)?$', re.IGNORECASE)\n\ndef normalize_arxiv_id(raw: str) -> str | None:\n    raw = raw.strip().rstrip('.').split('/abs/')[-1]\n    return raw if ARXIV_ID.match(raw) else None\n\npid = normalize_arxiv_id(user_input)\nif pid is None:\n    return error_response('invalid arXiv id')","typeGuard":null,"tryCatchPattern":"try:\n    path = await source.download_pdf(pid, dirpath)\nexcept ValueError as e:\n    if '未找到' in str(e):\n        return f'paper {pid} not found on arXiv — check the ID'\n    raise","preventionTips":["Strip URL prefixes, whitespace and version suffixes before passing IDs.","Resolve via search_by_id first and show a friendly not-found message.","In batch jobs, catch ValueError per paper so one bad ID does not abort the run."],"tags":["arxiv","api","validation","paper-id","download"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}