Skip to content

3D generation hangs forever on Japanese Windows: extension worker deadlocks when stderr reader thread dies with UnicodeDecodeError (cp932) #214

Description

@Haagen-kaz

Environment

  • Windows 11 Pro (Japanese locale, default console codepage cp932)
  • Modly with the hunyuan3d-mini-fast extension (torch 2.6.0+cu124, RTX 3060)

Symptom

On a Japanese-locale Windows machine, every 3D generation gets stuck forever (worker process at 0% CPU, never finishes). The UI progress bar sits around ~80%, but that part of the bar is smoothed/estimated progress, so the hang is easy to misread as "slow generation".

Root cause

In api/services/extension_process.py, the worker is spawned with subprocess.Popen(..., text=True) without an explicit encoding=. With text=True, Python uses the OS locale encoding for the pipes — cp932 on Japanese Windows.

The worker emits UTF-8 (and mixed-encoding output from native libs). As soon as a non-cp932 byte sequence arrives, the _stderr_loop reader thread dies with UnicodeDecodeError. With the reader thread dead, the stderr pipe fills up, and the worker then blocks forever inside a tqdm write mid-generation. From the outside it looks like a silent, permanent stall (CPU 0%).

Fix (verified locally)

Two small changes make generation work reliably on cp932 systems:

--- a/api/services/extension_process.py
+++ b/api/services/extension_process.py
@@ class ExtensionProcess:
         env["MODLY_API_DIR"] = str(Path(__file__).parent.parent)
+        # Force the worker's Python stdio to UTF-8 so it matches the utf-8
+        # pipe readers regardless of the OS locale (e.g. cp932).
+        env["PYTHONUTF8"] = "1"
@@ class ExtensionProcess:
             self._proc = subprocess.Popen(
                 [str(python), str(_RUNNER_PATH)],
                 stdin=subprocess.PIPE,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE,
                 text=True,
+                encoding="utf-8",
+                errors="replace",
                 bufsize=1,
                 env=self._build_env(),
             )
  • encoding="utf-8" makes the pipe readers independent of the OS locale.
  • errors="replace" keeps the reader threads alive even on mixed-encoding output from native libraries.
  • PYTHONUTF8=1 makes the worker side symmetric.

With this patch applied locally, generation completes normally on the same machine. This likely affects all non-UTF-8-locale Windows users (Japanese, Chinese, Korean, ...). Happy to open a PR if useful.

Activity

  1. self-assigned this
    on Jul 9, 2026
  2. Lorchie commented on Jul 9, 2026

    @Lorchie
    Collaborator

    Hi @Haagen-kaz, thanks a lot for the issue — great catch and a really solid diagnosis, nicely done! 🙏 Feel free to open a PR with the fix.

  3. Lorchie commented on Oct 9, 2026

    @Lorchie
    Collaborator

    Fixed and released (shipped in v0.4.2, and in v0.4.3, the current release). The extension worker now forces UTF-8 for its stdio, and its pipes are decoded as UTF-8. On a cp932 system, the stderr reader thread can no longer die and leave the worker stuck. A regression test covers the tqdm output that used to trigger it. Thanks again @Haagen-kaz for the diagnosis.

    If generation still hangs on Japanese-locale Windows with v0.4.3, feel free to reopen this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions