#300·LTX-2

Windows: invalid python storage in SafetensorsStateDictLoader when loading embeddings processor from LTX-2.5 split pack

Author: woodenriver05Created Aug 25, 2026Updated Aug 26, 2026

Summary

On Windows, scripts/train.py dies at Loading embeddings processor... with:

RuntimeError: Attempted to access the data pointer on an invalid python storage
  ltx_core/loader/sft_loader.py:36  (safe_open + get_tensor + .to(device, non_blocking=True, copy=False))

This is not an OOM. Peak VRAM at the crash was 25,831 / 32,607 MB (79.2%) on an RTX 5090 32GB. Preprocess (process_dataset.py) and transformer build both succeed. Triton on Windows works via triton-windows.

I could not find an existing LTX-2 issue with this traceback.

Environment

  • OS: Windows 11, RTX 5090 32GB
  • Clone: Lightricks/LTX-2 @ 400fd31 (2026-08-16 shallow)
  • Python: CPython 3.13.12 (uv sync venv)
  • torch: 2.13.0+cu132
  • triton: 3.7.1 (triton-windows<3.8)
  • bitsandbytes: 0.50.1 (installed by hand; pyproject marks it linux-only)
  • natten: not installed — Triton NA fallback is active and works (DiffVAE NA fallback: using Triton na3d)

Windows extras that the trainer docs call Linux-only are in fact working here: @triton.jit compiles and runs, AdamW8bit steps on CUDA. The failure is later, at embeddings-processor load.

What works before the crash

  1. uv sync + triton-windows + bitsandbytes
  2. Real @triton.jit kernel compile + execute
  3. AdamW8bit CUDA optimizer step
  4. process_dataset.py on 2 clips at 512x320x49 — latents 2 + conditions 2 (25MB)
  5. Transformer build (SDPA CUDNN > FLASH > EFFICIENT > MATH)

Weights (LTX-2.5 split pack, bf16 — not the Comfy int8-convrot files)

  • transformer: ltx-2.5-22b-dev-transformer-bf16.safetensors (39.13 GB) — F32 290 + BF16 4059
  • packed TE: gemma4-12b-with-proj-ltx-2.5-bf16.safetensors (24.46 GB) — BF16 681 + U8 5 (tokenizer/config assets)
  • video/audio VAE bf16 for preprocess only

Comfy *-comfy-int8-convrot files are a separate wall (Only Tensors of floating point and complex dtype can require gradients) and were not used for this run.

Loader path

trainer.py _load_models:

python
self._embeddings_processor = load_embeddings_processor(
    checkpoint_path=embedding_weight_paths(model_path, text_encoder_path),
    gemma_model_path=text_encoder_path,
    device=init_device,  # cuda:0
    dtype=torch.bfloat16,
)

For a split 2.5 pack, embedding_weight_paths() returns (transformer, packed_te) and load_embeddings_processor passes that tuple into SingleGPUModelBuilder. SafetensorsStateDictLoader.load then loops both shards:

python
with safetensors.safe_open(shard_path, framework="pt", device=str(device)) as f:
    for name in f.keys():
        value = f.get_tensor(name).to(device=device, non_blocking=True, copy=False)
        sd[key] = value

What we already ruled out

  • VRAM: 25,831 / 32,607 MB at the crash, 6.8 GB free, util 70%, 204 W.
  • Corrupt / truncated files: loading each file alone with safe_open(..., device='cuda') and get_tensor over every key succeeds (TE 686 tensors, transformer 4,349 tensors).
  • Console encoding: an earlier rich UnicodeEncodeError on cp1252 was a separate trap; this run used PYTHONUTF8=1 / PYTHONIOENCODING=utf-8.
  • Comfy int8 weights: not used.

So the remaining suspect is the combined CUDA load of transformer + packed TE into one dict via mmap-backed get_tensor + copy=False. Cause is still unconfirmed — we stopped retuning after the failure axis moved (dtype → console encoding → loader).

Related, not claimed identical

Windows + large safetensors + safe_open/get_tensor has other crash reports, e.g. Comfy-Org/ComfyUI#15424 (access violation on >10GB CLIP in a long-running process; standalone get_tensor ok). Different exception, similar class. Mentioning it only as a pointer.

Ask

Is embeddings-processor load on CUDA from the two-file split pack a supported path on Windows? If the intended device for that load is CPU (then move), or if copy=True / safetensors.torch.load_file(..., backend="pread") is the expected non-mmap path, a one-line note in the trainer would save a lot of false OOM debugging.