[Windows] documents plugin render_docx.py: malformed -env:UserInstallation URI crashes soffice; missing subprocess timeout turns failures into silent 2-minute hangs

Open 💬 2 comments Opened Jun 12, 2026 by su-nyx

What version of the Codex App are you using (From “About Codex” dialog)?

Version 26.608.12217

What subscription do you have?

Plus

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

What issue are you seeing?

Environment

  • Codex desktop app on Windows 11 (Build 26200), commands executed in the Windows sandbox (sandbox user identity, separate from the logged-in user)
  • Documents plugin cache version: 26.601.10930
  • Script: .codex\plugins\cache\openai-primary-runtime\documents\26.601.10930\skills\documents\render_docx.py
  • LibreOffice 26.2.3.2 at C:\Program Files\LibreOffice, on the machine PATH (soffice --version works inside the sandbox)
  • Note: the Windows user profile path contains a space (C:\Users\First Last)

Summary

render_docx.py cannot render any DOCX on this Windows setup. The root cause is the UserInstallation profile URI construction, which is POSIX-only. A secondary robustness issue (no subprocess timeout, fully piped output) turned the failure into two silent 2 minute command timeouts during a real task, with zero diagnostic output.

Bug 1: malformed -env:UserInstallation URI on Windows

convert_to_pdf() builds the profile argument by string concatenation, at three call sites:

"-env:UserInstallation=file://" + user_profile

user_profile comes from tempfile.TemporaryDirectory(), so on Windows this produces:

file://C:\Users\First Last\AppData\Local\Temp\soffice_profile_xxxx

This is not a valid file URI: only two slashes (the path lands in the URI authority position), backslash separators, and unencoded spaces. The concatenation only works on POSIX because absolute paths begin with "/".

Reproduction (same DOCX, same outdir, only the URI form differs):

  • Malformed URI, PowerShell (& soffice, resolves to soffice.com): exit 1 in about 1.4 s, no stdout/stderr, no PDF
  • Malformed URI, Python subprocess with list args and PIPE (bare "soffice" and explicit "soffice.com" both tested): exit 3221226505 (0xC0000409, STATUS_STACK_BUFFER_OVERRUN, fail-fast abort) in about 1 s, no output, no PDF
  • Correct URI (file:///C:/Users/First%20Last/AppData/Local/Temp/lo_probe_b): exit 0 in about 10 s, valid PDF produced

So the malformed URI does not merely fail; under CreateProcess launch semantics it crashes soffice outright via fail-fast, which also explains the complete absence of error output.

One line fix at all three call sites:

from pathlib import Path
"-env:UserInstallation=" + Path(user_profile).as_uri()

Bug 2: no subprocess timeout, fully piped output

_run_cmd() calls subprocess.run() with stdout and stderr PIPEd and no timeout argument, and captured logs are only surfaced after the process completes. If soffice stalls for any reason, the script emits nothing until the caller's command budget kills it.

Real-world impact: during a document task on this machine, both render_docx.py invocations ran for exactly 2m00s and were killed by the harness (exit 124) with no output at all. The same DOCX files converted in seconds via a direct soffice call with a correctly formed fresh profile URI. I could not re-reproduce the stall afterwards (the malformed URI now fails fast), so some additional same-day state was involved. Regardless, a renderer that shells out should bound its subprocesses and surface captured stderr on failure even without --verbose.

Supporting observations

  • _build_lo_env() only sets HOME, XDG_CONFIG_HOME and XDG_CACHE_HOME, which LibreOffice ignores on Windows (it uses %APPDATA%). In the Codex Windows sandbox the inherited %APPDATA% points into the logged-in user's profile, which the sandbox identity cannot write: New-Item into %APPDATA%\LibreOffice returns UnauthorizedAccessException. The "writable profile" safety mechanism is therefore fully inert on Windows.
  • The script already contains a macOS-only shim (_default_macos_tmpdir_for_soffice) for a similar platform-specific LibreOffice issue on macOS; Windows has no equivalent handling.
  • The PNG stage depends on pdf2image, which requires Poppler binaries that are not bundled in the Windows runtime, so even with Bug 1 fixed the script cannot complete on a default Windows install (pdf2image.exceptions.PDFInfoNotInstalledError).

Suggested fixes

  1. Build the UserInstallation URI with Path(user_profile).as_uri() at all three call sites.
  2. Add a timeout to _run_cmd() and print captured stderr on nonzero exit without requiring --verbose.
  3. On Windows, resolve soffice.com explicitly for console semantics.
  4. Bundle Poppler for Windows or fall back to a pure Python rasterizer such as pypdfium2 for the PDF to PNG stage.

What steps can reproduce the bug?

The core defect reproduces on any Windows machine with LibreOffice on PATH, without Codex in the loop:

  1. Pick any valid .docx file.
  1. Run soffice with the profile URI exactly as render_docx.py constructs it ("file://" + a Windows temp path, three call sites in convert_to_pdf):

& soffice "-env:UserInstallation=file://C:\Users\First Last\AppData\Local\Temp\lo_probe_a" --headless --norestore --convert-to pdf --outdir "C:\probe_out_a" "C:\path\to\test.docx"

Observed: silent failure in about 1.4 s, exit 1, no PDF. Launched via Python subprocess.run with list args and piped output (which is how the script launches it), the same command exits with 3221226505 (0xC0000409, fail-fast abort), also silent, no PDF.

  1. Run the identical command with a correctly formed URI:

& soffice "-env:UserInstallation=file:///C:/Users/First%20Last/AppData/Local/Temp/lo_probe_b" --headless --norestore --convert-to pdf --outdir "C:\probe_out_b" "C:\path\to\test.docx"

Observed: exit 0 in about 10 s, valid PDF produced.

  1. End to end in the Codex app: ask the agent to create a DOCX and render it with the documents plugin's render_docx.py on Windows. In my session both invocations ran for exactly 2m00s and were killed by the harness (exit 124) with no output.

Session id: available on request (the core defect reproduces outside Codex entirely).

What is the expected behavior?

render_docx.py converts the DOCX and produces page-<N>.png files (and the intermediate PDF with --emit_pdf) on Windows, as it does on Linux and macOS. With the UserInstallation URI built via Path(user_profile).as_uri(), the same conversion succeeds in about 10 s on this machine. If conversion cannot succeed, the script should fail fast and surface the captured stderr instead of hanging silently until the command timeout.

Additional information

Full PowerShell and Python probe transcripts are available on request. Note that the sandbox identity cannot write to the inherited %APPDATA% (presumably by design), so the fix should not assume the default LibreOffice profile location is usable; a correctly formed per-run UserInstallation URI, which is what the script already intends, is the right approach.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗