binary-husky/gpt_academic · error · RuntimeError

LibreOffice转换失败

Error message

LibreOffice转换失败: {error_msg}

What it means

Raised as RuntimeError when `libreoffice --headless --convert-to pdf:writer_pdf_Export <doc> --outdir <dir>` exits non-zero. The message embeds result.stderr, or '未知错误' when stderr is empty. It means LibreOffice started but the conversion subprocess itself failed.

Solutions

  1. Reproduce manually with the same args to see the full error: libreoffice --headless --convert-to pdf:writer_pdf_Export file.docx --outdir /tmp/out
  2. If converting concurrently, give each run an isolated profile: add -env:UserInstallation=file:///tmp/lo_profile_<id> to the command
  3. Ensure pdf_path.parent exists (mkdir parents=True) before calling
  4. Install basic fonts in containers: apt-get install -y fontconfig fonts-dejavu
  5. Verify the docx opens in LibreOffice GUI / is not encrypted

Example fix

// before
result = subprocess.run(
    ['libreoffice', '--headless', '--convert-to', 'pdf:writer_pdf_Export',
     str(word_path), '--outdir', str(pdf_path.parent)],
    capture_output=True, text=True)

// after
pdf_path.parent.mkdir(parents=True, exist_ok=True)
result = subprocess.run(
    ['-env:UserInstallation=file:///tmp/lo_profile_' + str(os.getpid()),
     'libreoffice', '--headless', '--convert-to', 'pdf:writer_pdf_Export',
     str(word_path), '--outdir', str(pdf_path.parent)],
    capture_output=True, text=True, timeout=120)
Defensive patterns

Strategy: fallback

Validate before calling

import shutil, subprocess, tempfile

def libreoffice_sane() -> bool:
    if shutil.which('libreoffice') is None:
        return False
    with tempfile.TemporaryDirectory() as d:
        (Path(d)/'t.docx').write_bytes(minimal_docx_bytes())
        r = subprocess.run(['libreoffice', '--headless', '--convert-to', 'pdf',
                            str(Path(d)/'t.docx'), '--outdir', d],
                           capture_output=True, timeout=60)
        return r.returncode == 0

Try / catch

try:
    pdf = WordToPdfConverter.convert_to_pdf(docx)
except RuntimeError as e:
    if 'LibreOffice转换失败' in str(e):
        log.error('LO stderr: %s', e)
        pdf = convert_with_isolated_profile(docx)  # -env:UserInstallation retry

Prevention

When it happens

Trigger: Corrupt or password-protected .docx; an outdir that does not exist or is not writable; a LibreOffice profile lock from a concurrently running instance; unsupported legacy .doc content; missing fonts causing writer filters to fail; word_path containing shell-hostile characters passed through subprocess list args (usually fine) but pointing to a nonexistent file.

Common situations: Running multiple conversions in parallel — LibreOffice headless refuses concurrent runs sharing a user profile; Docker containers missing fonts (fontconfig) or a HOME for the profile; outdir derived from pdf_path.parent that was never created.

Related errors


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

Appendix: source

Thrown at crazy_functions/doc_fns/conversation_doc/word2pdf.py:56

            if platform.system() == 'Linux':
                # Linux系统需要安装libreoffice
                which_result = subprocess.run(['which', 'libreoffice'], capture_output=True, text=True)
                if which_result.returncode != 0:
                    raise RuntimeError("请先安装LibreOffice: sudo apt-get install libreoffice")

                print(f"开始转换Word文档: {word_path} 到 PDF")

                # 使用subprocess代替os.system
                result = subprocess.run(
                    ['libreoffice', '--headless', '--convert-to', 'pdf:writer_pdf_Export',
                     str(word_path), '--outdir', str(pdf_path.parent)],
                    capture_output=True, text=True
                )

                if result.returncode != 0:
                    error_msg = result.stderr or "未知错误"
                    print(f"LibreOffice转换失败,错误信息: {error_msg}")
                    raise RuntimeError(f"LibreOffice转换失败: {error_msg}")

                print(f"LibreOffice转换输出: {result.stdout}")

                # 如果输出路径与默认生成的不同,则重命名
                default_pdf = word_path.with_suffix('.pdf')
                if default_pdf != pdf_path and default_pdf.exists():
                    os.rename(default_pdf, pdf_path)
                    print(f"已将PDF从 {default_pdf} 重命名为 {pdf_path}")

                # 验证PDF是否成功生成
                if not pdf_path.exists() or pdf_path.stat().st_size == 0:
                    raise RuntimeError("PDF生成失败或文件为空")

                print(f"PDF转换成功,文件大小: {pdf_path.stat().st_size} 字节")
            else:
                # Windows和MacOS使用docx2pdf
                print(f"使用docx2pdf转换 {word_path} 到 {pdf_path}")
                convert(word_path, pdf_path)

View on GitHub (pinned to d6bde0fa54)