TouchDiffusion kept telling me Active engine: None. The engine was fine. The model files were fine. The cause was sys.path order.

The symptom chain

name 'StreamDiffusionWrapper' is not defined Numpy is not available Model load has failed. Doesn't exist. cannot access local variable 'pipe' where it is not associated with a value 

Active engine stayed None, Size (WxH) showed 0 0, and every Load engine did nothing.

Why it looks like the engine

TouchDiffusionExt imports the wrapper at DAT compile time inside a bare try/except. When the import fails, the class still compiles, StreamDiffusionWrapper is never bound, and every later call raises name 'StreamDiffusionWrapper' is not defined. The log only shows the deferred name error, not the real cause.

The real cause: host paths win

TouchDesigner inserts its own site-packages before any path the component adds, and on 2023 it also picks up the system Python 3.11 site-packages. The portable build of TouchDiffusion ships its own embedded_python with matched versions, so this is what happens:

  • On TD 2025 the bundled numpy is 2.1.2. The transformers in the portable env requires numpy<2, so the import chain aborts.
  • On TD 2023 numpy is fine, but the system Python contributes a torch 2.6 and a newer huggingface_hub without cached_download, which breaks the older diffusers in the portable env.

torch decides its numpy bridge at import time. That is why Numpy is not available is unrecoverable in-process, and why from_pretrained never returns a pipeline: pipe stays unbound and the wrapper dies on it.

What does not work

All of these were tried:

  • PYTHONPATH pointing at the portable site-packages. TD's own paths still win.
  • sitecustomize.py, usercustomize.py, or a .pth inside TD's site-packages. TD starts Python with the site hooks not running; sitecustomize never gets imported.
  • sys.path.insert alone at the top of the Ext on TD 2025. Too late for numpy.
  • Deleting torch from sys.modules and reimporting it. PyTorch asserts with THPDtypeType.tp_dict == nullptr INTERNAL ASSERT FAILED at "torch/csrc/Dtype.cpp".
  • Calling activate_stream from a threading.Thread. TD operators can only be touched on the main thread: SystemError: <td.OPShortcut> returned NULL.

What works

Tested on TD 2023.12600, Windows, RTX 4070 Laptop 8 GB, with the engines shipped in the portable build (512x512, batch 3).

  1. Launch TouchDesigner with PYTHONNOUSERSITE=1 so the system user site is out of the picture.
  2. At the very top of the TouchDiffusionExt DAT, before any import:
import sys SP = r"<PORTABLE>/embedded_python/Lib/site-packages" sys.path = [p for p in sys.path if not ("Programs" in p and "Python311" in p and "embedded" not in p)] if SP not in sys.path: sys.path.insert(0, SP) 
  1. Re-init, select the engine, Load engine. The log should print TensorRT acceleration enabled. and Engine activated, and Active engine fills in.

Two side notes: Warning: '.venv/Lib/site-packages' is not a valid directory is harmless, the portable build uses embedded_python. And TouchDiffusion folder must be the portable root, the folder containing embedded_python/, StreamDiffusion/ and engines/, not its parent.

Credit

The numpy angle was already reported in issue #32, and the torch version angle in issue #38. The missing piece was path precedence, which is what issue #36 is about. The pipe error in issue #29 comes from building an engine in the web UI, a different flow.