Repository navigation
Conversation
Identification stores the component key instead of an absolute path, so records survive the install move; legacy absolute records are rebased onto config.path, preferring the model's own folder. SDNQ discovery skips index keys that are not plain folder names.
lstein
left a comment
There was a problem hiding this comment.
Thanks for tracking this down. The diagnosis is right: the pipeline is identified in its tmpinstall_* staging folder, the installer moves it and rewrites only config.path, and the loader then opens a component path that no longer exists. I confirmed the original fix repairs an affected real-world record (the "Z-Image Turbo (SDNQ uint4 + SVD)" starter model).
An adversarial review found two problems with the load-time-only rebase. Since maintainers can push here, I've pushed f128d58 on top of your commit rather than asking you to iterate:
-
The root came from
fallback.parent, which is not always the model folder. The transformer loaders (flux.py_load_transformer_from_folder,z_image.py_load_from_diffusers_folder) pass the model folder itself as the fallback when it has notransformer/subfolder. For a transformer under a non-standard index key, the rebase then looked in the models directory. It returned the stale path, or picked up an unrelated same-named entry beside the model, whileget_size_fssized a different folder. The resolver now usesconfig.pathas the root; it is absolute by the time any component is resolved. -
Identification kept writing absolute paths, and an existing recorded path won.
install_pathidentifies a local folder before moving it, so local installs persisted the source path (e.g.~/Downloads/X/text_encoder) indefinitely. The move emptiesXbut leaves it in place. If a different pipeline was later placed there, the installed model silently loaded that pipeline's text encoder, tokenizer, VAE and transformer. I reproduced this with a realinstall_path. The same happens when a models dir is copied and the old copy is kept.
What the push changes:
-
Identification (the three SDNQ diffusers pipelines, plus SD3) records the component key relative to the model folder, so new records survive any move.
-
For records already in the DB, the model's own same-named folder wins. The recorded absolute path is kept only when the model has no such folder, which covers a symlinked component that was recorded by its target's name. When nothing exists, the path returned is inside the model folder. Users then get an error naming the installed model, not the "Repo id must be in the form…" error from the original report.
-
SDNQ discovery skips
model_index.jsonkeys that aren't plain folder names (e.g.../vae). Since the key is now joined onto wherever the model lives, the folder validated at identification is guaranteed to be the one loaded. -
Tests:
- an identify →
install_path→ resolve test through the real installer; - exact stored-key assertions for FLUX.1/FLUX.2/Z-Image;
- escape-key tests for each SDNQ pipeline;
- a transformer-fallback regression;
- legacy-record cases.
Two of the original resolver tests asserted the previous precedence ("keep an existing external path", "keep the missing staging path"). Both are now inverted by design, so I replaced them.
- an identify →
Mutation-checked: reverting each fix (the original resolver, existing-recorded-wins, absolute identification, the plain-key guards) fails at least one test. The model-config, model-load and model-install suites pass locally.
Compatibility note: a record written by this version stores relative component keys. Older builds (v6.14.2 and earlier) would resolve them against the working directory, so loading such a model after a downgrade fails until the model is reidentified. Downloaded SDNQ pipelines were already broken on those versions, so in practice this only affects SDNQ pipelines registered in place. Worth a line in the release notes.
Merge plan: after this lands on main, it should be cherry-picked into v6-bugfixes. The bug has been present since v6.14.0. The patch applies cleanly there; v6's resolve_submodel_path and its callers match main.
Summary
tmpinstall_*staging directory after the pipeline is moved into the managed models directory.model_index.jsoncomponent names, and the existing failure behavior when neither path exists.The installer probes the downloaded pipeline before
install_path()moves it. Identification records absolute paths for direct child components, while registration updates only the top-level model path and stores managed paths relative to the models directory. Later, the shared resolver therefore returns a deleted staging path, which Transformers interprets as a Hub repository identifier. The resolved loader fallback—not the persisted relativeconfig.path—is the authoritative current root.Related Issues / Discussions
Closes #9580
QA Instructions
The relocation regression fails before the final implementation when it models a managed record with relative
config.path: the resolver returns the deleted staging path instead of the installed component. It passes after the resolver derives the absolute root fromfallback.parent.After the fix:
git diff --checkand the focused sensitive-path scan also pass. The pytest run emits one existingpytest-asyncioconfiguration warning unrelated to this change.Merge Plan
No special merge plan is required; this is a focused loader-path fix with regression coverage.
Checklist
What's Newcopy (if doing a release after this PR) (not applicable)AI-assisted tooling was used to trace the install lifecycle and develop the focused patch and tests; all listed checks were run against the submitted commit.