Skip to content

fix(models): rebase relocated submodel paths - #9592

Merged
lstein merged 4 commits into
invoke-ai:mainfrom
wunianze666-netizen:fix/issue-9580-relocated-submodel-paths-main
Oct 15, 2026
Merged

lstein merged 4 commits into
invoke-ai:mainfrom
wunianze666-netizen:fix/issue-9580-relocated-submodel-paths-main

Conversation

@wunianze666-netizen

@wunianze666-netizen wunianze666-netizen commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Fix remote SDNQ pipeline installs retaining absolute submodel paths from the tmpinstall_* staging directory after the pipeline is moved into the managed models directory.
  • Rebase a recorded component onto the loader's resolved current model root only when the recorded path is missing and the same-named component exists under that root.
  • Preserve valid external component paths, arbitrary model_index.json component 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 relative config.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 from fallback.parent.

After the fix:

python -m pytest tests/backend/model_manager/load/test_load_default_helpers.py tests/backend/model_manager/configs/test_z_image_sdnq_identification.py tests/backend/model_manager/configs/test_sdnq_pipeline_submodel_discovery.py -o addopts= -p no:cov -q
63 passed

python -m ruff check invokeai/backend/model_manager/load/load_default.py tests/backend/model_manager/load/test_load_default_helpers.py
All checks passed!

python -m ruff format --check invokeai/backend/model_manager/load/load_default.py tests/backend/model_manager/load/test_load_default_helpers.py
2 files already formatted

git diff --check and the focused sensitive-path scan also pass. The pytest run emits one existing pytest-asyncio configuration warning unrelated to this change.

Merge Plan

No special merge plan is required; this is a focused loader-path fix with regression coverage.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • Changes to a redux slice have a corresponding migration (not applicable)
  • Documentation added / updated (if applicable) (not applicable; behavior is covered by tests)
  • Updated What's New copy (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.

@github-actions github-actions Bot added python PRs that change python files backend PRs that change backend files python-tests PRs that change python tests labels Sep 18, 2026
@lstein lstein added 6.14.2 6.14.3 Candidate for 6.14.3 bugfix release and removed 6.14.2 labels Sep 21, 2026
@lstein lstein assigned lstein and unassigned Pfannkuchensack Oct 15, 2026
@lstein lstein added the 7.0.0 label Oct 15, 2026
@lstein lstein moved this to 7.0 Theme: Modular Design in Invoke - Community Roadmap Oct 15, 2026
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 lstein left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. 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 no transformer/ 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, while get_size_fs sized a different folder. The resolver now uses config.path as the root; it is absolute by the time any component is resolved.

  2. Identification kept writing absolute paths, and an existing recorded path won. install_path identifies a local folder before moving it, so local installs persisted the source path (e.g. ~/Downloads/X/text_encoder) indefinitely. The move empties X but 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 real install_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.json keys 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.

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.

@lstein
lstein enabled auto-merge October 15, 2026 03:21
@lstein
lstein merged commit 358257b into invoke-ai:main Oct 15, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.14.3 Candidate for 6.14.3 bugfix release 7.0.0 backend PRs that change backend files python PRs that change python files python-tests PRs that change python tests

Projects

Status: 7.0 Theme: Modular Design

Development

Successfully merging this pull request may close these issues.

[bug]: repo_name error when using starter SDQN model

3 participants