Describe the bug
ModularPipeline.from_pretrained(local_dir) / blocks.init_pipeline(local_dir) followed by load_components() does not load the components from local_dir when the directory contains a modular_model_index.json whose specs carry a hub repo id. The specs are taken verbatim from the file, so every component is resolved against the hub instead of the directory that already holds it. For a converted checkpoint like MiniMaxAI/MiniMax-H3 — whose index files ship nine "pretrained_model_name_or_path": "MiniMaxAI/MiniMax-H3" entries — a user who downloaded the snapshot to a local directory (e.g. hf download MiniMaxAI/MiniMax-H3 --local-dir models/minimax-h3) gets a second, full 134 GB download into the hub cache on first load_components(). Offline, the components simply fail to load and stay None.
The asymmetry is in modular_pipeline.py (v0.40.0):
- with
modular_model_index.json present (line 1749), each spec is rebuilt from the file as-is (line 1755) — the hub id wins over the local directory;
- without it, the
model_index.json fallback builds the spec as "repo": pretrained_model_name_or_path (line 1768) — i.e. the local directory, which is the expected behaviour.
So a local snapshot works only if the user hand-edits both index files to point at the local path (which is what we do).
Reproduction
No download needed — an empty cache plus offline mode makes the hub lookup fail loudly instead of pulling 134 GB. snapshot/ is a local copy of MiniMaxAI/MiniMax-H3 with its original index files.
import os
os.environ["HF_HOME"] = "/tmp/empty_hf_home" # fresh, empty cache
os.environ["HF_HUB_OFFLINE"] = "1"
from diffusers.modular_pipelines.minimax_h3 import MiniMaxH3Blocks
pipe = MiniMaxH3Blocks().init_pipeline("snapshot") # contains scheduler/scheduler_config.json
pipe.load_components(names=["scheduler"]) # smallest component, 4 KB on disk
print(pipe.scheduler) # -> None
Rewriting the nine pretrained_model_name_or_path entries in snapshot/modular_model_index.json (and model_index.json) to the local path, and running the same script, loads MiniMaxH3Scheduler from disk.
Logs
ValueError: Unable to load scheduler using load method: MiniMaxAI/MiniMax-H3 does not appear to have a file named scheduler_config.json.
(logged by `load_components`; the component is left as `None`. With the network on, the same call downloads the whole repo into the cache.)
### Expected behavior / proposed fix
When `pretrained_model_name_or_path` is a local directory, specs read from its `modular_model_index.json` should resolve against that directory whenever `<local_dir>/<subfolder>` exists — the same thing the `model_index.json` fallback already does — with the hub id kept only as a fallback for pruned snapshots that intentionally omit components. Alternatively, `save_pretrained` could write local/relative references so a downloaded snapshot is self-contained. Happy to open a PR for the first option if that shape is acceptable.
System Info
- 🤗 Diffusers version: 0.40.0 (lines above from the v0.40.0 tag; same on main)
- Platform: macOS-26.6.2-arm64-arm-64bit-Mach-O
- Python version: 3.14.5
- PyTorch version (GPU?): 2.14.0.dev20260808 (MPS)
- Huggingface_hub version: 1.27.0
- Transformers version: 5.14.1
- Accelerate version: 1.14.0
- Accelerator: Apple M5 Max, 128 GB unified memory
- Using GPU in script?: no (loading only)
- Using distributed or parallel set-up in script?: no
Who can help?
@apolinario (MiniMax-H3 integration, #14355) — and whoever owns Modular Diffusers loading
Describe the bug
ModularPipeline.from_pretrained(local_dir)/blocks.init_pipeline(local_dir)followed byload_components()does not load the components fromlocal_dirwhen the directory contains amodular_model_index.jsonwhose specs carry a hub repo id. The specs are taken verbatim from the file, so every component is resolved against the hub instead of the directory that already holds it. For a converted checkpoint likeMiniMaxAI/MiniMax-H3— whose index files ship nine"pretrained_model_name_or_path": "MiniMaxAI/MiniMax-H3"entries — a user who downloaded the snapshot to a local directory (e.g.hf download MiniMaxAI/MiniMax-H3 --local-dir models/minimax-h3) gets a second, full 134 GB download into the hub cache on firstload_components(). Offline, the components simply fail to load and stayNone.The asymmetry is in
modular_pipeline.py(v0.40.0):modular_model_index.jsonpresent (line 1749), each spec is rebuilt from the file as-is (line 1755) — the hub id wins over the local directory;model_index.jsonfallback builds the spec as"repo": pretrained_model_name_or_path(line 1768) — i.e. the local directory, which is the expected behaviour.So a local snapshot works only if the user hand-edits both index files to point at the local path (which is what we do).
Reproduction
No download needed — an empty cache plus offline mode makes the hub lookup fail loudly instead of pulling 134 GB.
snapshot/is a local copy ofMiniMaxAI/MiniMax-H3with its original index files.Rewriting the nine
pretrained_model_name_or_pathentries insnapshot/modular_model_index.json(andmodel_index.json) to the local path, and running the same script, loadsMiniMaxH3Schedulerfrom disk.Logs
System Info
Who can help?
@apolinario (MiniMax-H3 integration, #14355) — and whoever owns Modular Diffusers loading