binary-husky/gpt_academic · error · RuntimeError

解析PDF失败,请检查PDF是否损坏。

Error message

解析PDF失败,请检查PDF是否损坏。

What it means

In the GROBID PDF-translation plugin loop, parse_pdf() returns None (its internal guard swallows exceptions and returns None for some failure modes) and this explicit check raises RuntimeError before translation begins. Note parse_pdf is lru_cached, so a previously failed parse of the same (path, url) will keep returning the cached None.

Source

Thrown at crazy_functions/pdf_fns/parse_pdf_grobid.py:21

from toolbox import update_ui, promote_file_to_downloadzone, update_ui_latest_msg, disable_auto_promotion
from toolbox import write_history_to_file, promote_file_to_downloadzone, get_conf, extract_archive
from crazy_functions.pdf_fns.parse_pdf import parse_pdf, translate_pdf

def 解析PDF_基于GROBID(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, grobid_url):
    import copy, json
    TOKEN_LIMIT_PER_FRAGMENT = 1024
    generated_conclusion_files = []
    generated_html_files = []
    DST_LANG = "中文"
    from crazy_functions.pdf_fns.report_gen_html import construct_html
    for index, fp in enumerate(file_manifest):
        chatbot.append(["当前进度:", f"正在连接GROBID服务,请稍候: {grobid_url}\n如果等待时间过长,请修改config中的GROBID_URL,可修改成本地GROBID服务。"]); yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
        article_dict = parse_pdf(fp, grobid_url)
        grobid_json_res = os.path.join(get_log_folder(), gen_time_str() + "grobid.json")
        with open(grobid_json_res, 'w+', encoding='utf8') as f:
            f.write(json.dumps(article_dict, indent=4, ensure_ascii=False))
        promote_file_to_downloadzone(grobid_json_res, chatbot=chatbot)
        if article_dict is None: raise RuntimeError("解析PDF失败,请检查PDF是否损坏。")
        yield from translate_pdf(article_dict, llm_kwargs, chatbot, fp, generated_conclusion_files, TOKEN_LIMIT_PER_FRAGMENT, DST_LANG, plugin_kwargs=plugin_kwargs)
    chatbot.append(("给出输出文件清单", str(generated_conclusion_files + generated_html_files)))
    yield from update_ui(chatbot=chatbot, history=history) # 刷新界面

View on GitHub (pinned to d6bde0fa54)

Solutions

  1. First fix the underlying parse failure (GROBID availability, PDF validity — see errors 70/71)
  2. If retrying in the same process, clear the cache: parse_pdf.cache_clear()
  3. Verify the file is a readable PDF and not zero-byte after upload
  4. Check the chatbot status line above — it shows the GROBID URL being used; test it with curl

Example fix

# before
article_dict = parse_pdf(fp, grobid_url)

# after
from crazy_functions.pdf_fns.parse_pdf import parse_pdf
parse_pdf.cache_clear()  # on retry, avoid stale cached None
article_dict = parse_pdf(fp, grobid_url)
Defensive patterns

Strategy: validation

Validate before calling

article = parse_pdf(str(fp), grobid_url)  # normalize cache key
if article is None:
    parse_pdf.cache_clear()
    article = parse_pdf(str(fp), grobid_url)  # one fresh attempt, not cached None
if article is None:
    raise RuntimeError(f'{fp} unparseable; see GROBID logs')

Type guard

def is_parsed_article(d) -> bool:
    return isinstance(d, dict) and bool(d.get('sections') or d.get('title'))

Try / catch

try:
    yield from translate_pdf(...)
except RuntimeError as e:
    if '解析PDF失败' in str(e):
        chatbot.append(['错误', '该PDF无法解析,请检查文件是否损坏或改用Doc2x解析'])
        yield from update_ui(chatbot=chatbot)

Prevention

When it happens

Trigger: parse_pdf hit an exception it converts to None (see error 70/71 paths); file path passed as a Path object vs string changing the lru_cache key; the same file retried in one process getting the cached None result.

Common situations: Retrying a failed translation in the same session and hitting the cached None; batch jobs where the first GROBID failure poisons the cache entry; mixed str/Path arguments for fp.

Related errors


AI-assisted analysis of binary-husky/gpt_academic@d6bde0fa54 (2026-08-14). Data as JSON: /api/errors/d360b34daf761a8a. Report an issue: GitHub.