{"record":{"id":"d89e6d5ff256c615","repo":"binary-husky/gpt_academic","slug":"os-path-basename-fp-timeout-seconds","errorCode":null,"errorMessage":"处理文件 {os.path.basename(fp)} 超时（{TIMEOUT_SECONDS}秒）","messagePattern":"处理文件 (.+?) 超时（(.+?)秒）","errorType":"exception","errorClass":"TimeoutError","httpStatus":null,"severity":"error","filePath":"crazy_functions/Document_Conversation.py","lineNumber":89,"sourceCode":"                thread._timeout_occurred = True\n\n        # 设置超时标记\n        thread = threading.current_thread()\n        thread._timeout_occurred = False\n\n        # 设置超时时间为30秒，给予更多处理时间\n        TIMEOUT_SECONDS = 30\n        timer = threading.Timer(TIMEOUT_SECONDS, timeout_handler)\n        timer.start()\n\n        try:\n            fp, project_folder = file_info\n            fragments = []\n\n            # 定期检查是否超时\n            def check_timeout():\n                if hasattr(thread, '_timeout_occurred') and thread._timeout_occurred:\n                    raise TimeoutError(f\"处理文件 {os.path.basename(fp)} 超时（{TIMEOUT_SECONDS}秒）\")\n\n            # 更新状态\n            mutable_status[0] = \"检查文件大小\"\n            mutable_status[1] = time.time()\n            check_timeout()\n\n            # 文件大小检查\n            if os.path.getsize(fp) > self.max_file_size:\n                self.failed_files.append((fp, f\"文件过大：超过{self.max_file_size / 1024 / 1024}MB\"))\n                mutable_status[2] = \"文件过大\"\n                return fragments\n\n            # 更新状态\n            mutable_status[0] = \"提取文件内容\"\n            mutable_status[1] = time.time()\n\n            # 提取内容 - 使用单独的超时控制\n            content = None","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/crazy_functions/Document_Conversation.py#L71-L107","documentation":"This TimeoutError is the cooperative 30-second per-file budget in BatchDocumentSummarizer. A threading.Timer sets _timeout_occurred on the worker thread; the next check_timeout() call raises with the filename. It marks that one file failed and returns no fragments, but it cannot interrupt code that is already blocked.","triggerScenarios":"A worker passes the size check, extract_text, token splitting, or fragment construction and reaches a checkpoint after the 30-second timer fired. Large or malformed documents, many fragments, slow markitdown/LLamaIndex parsing, or a worker blocked past the deadline all produce it.","commonSituations":"Uploading a near-10MB PDF or presentation; processing archives containing many files with max_workers up to 32; scanned or complex PDFs; slow disks in Docker; a document whose extraction subprocess hangs until the global timer is already set.","solutions":["Inspect summarizer.failed_files and mutable_status to identify the exact file; remove or process that file separately.","Keep files well below max_file_size and split large documents before upload.","If the workload legitimately needs more time, raise TIMEOUT_SECONDS or make it configurable rather than relying on the hardcoded 30 seconds.","Reduce concurrency so parser subprocesses are not starved on CPU or disk.","Replace the flag-based timer with a real subprocess timeout for extract_text if blocking extraction is the cause."],"exampleFix":"# before\nTIMEOUT_SECONDS = 30\ntimer = threading.Timer(TIMEOUT_SECONDS, timeout_handler)\n\n# after\nTIMEOUT_SECONDS = int(os.environ.get(\"DOC_CONVERSATION_TIMEOUT\", \"30\"))\ntimer = threading.Timer(TIMEOUT_SECONDS, timeout_handler)\n","handlingStrategy":"validation","validationCode":"from crazy_functions.rag_fns.rag_file_support import supports_format\nMAX_SIZE = 10 * 1024 * 1024\n\ndef acceptable_document(fp):\n    return os.path.isfile(fp) and os.path.getsize(fp) <= MAX_SIZE and os.path.splitext(fp.lower())[1] in supports_format\n","typeGuard":"def acceptable_document(fp) -> bool:\n    return (\n        isinstance(fp, str)\n        and os.path.isfile(fp)\n        and os.path.getsize(fp) <= 10 * 1024 * 1024\n        and os.path.splitext(fp.lower())[1] in {\".pdf\", \".docx\", \".txt\", \".md\", \".pptx\", \".csv\", \".epub\", \".ipynb\"}\n    )\n","tryCatchPattern":"try:\n    fragments = summarizer._process_single_file_with_timeout(file_info, status)\nexcept TimeoutError as e:\n    summarizer.failed_files.append((file_info[0], str(e)))\n    fragments = []\n","preventionTips":["Filter unsupported and oversized files before submitting the batch.","Split large PDFs and presentations before upload.","Set a per-file timeout based on measured parser performance.","Watch failed_files rather than assuming every uploaded file was processed."],"tags":["timeout","documents","llama-index","threading"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}