Skip to content

Refactor model directory structure and add new configuration files#14768

Open
Samith-NM wants to merge 2 commits into
Comfy-Org:masterfrom
Samith-NM:master
Open

Refactor model directory structure and add new configuration files#14768
Samith-NM wants to merge 2 commits into
Comfy-Org:masterfrom
Samith-NM:master

Conversation

@Samith-NM

@Samith-NM Samith-NM commented Jul 4, 2026

Copy link
Copy Markdown
  • Deleted obsolete model directories: controlnet, detection, diffusers, diffusion_models, embeddings, frame_interpolation, geometry_estimation, gligen, hypernetworks, latent_upscale_models, loras, model_patches, optical_flow, photomaker, style_models, text_encoders, unet, upscale_models, vae, vae_approx.
  • Created new model directories for audio_encoders, background_removal, checkpoints, clip, clip_vision, and updated configs for various models including anything_v3, v1-inference, v2-inference, and inpainting.
  • Added detailed configuration files for model training and inference, including parameters for learning rates, model architectures, and data handling.
  • How come we can't relocate instances? #14760 Fixes
    Closes How come we can't relocate instances? #14760

- Deleted obsolete model directories: controlnet, detection, diffusers, diffusion_models, embeddings, frame_interpolation, geometry_estimation, gligen, hypernetworks, latent_upscale_models, loras, model_patches, optical_flow, photomaker, style_models, text_encoders, unet, upscale_models, vae, vae_approx.
- Created new model directories for audio_encoders, background_removal, checkpoints, clip, clip_vision, and updated configs for various models including anything_v3, v1-inference, v2-inference, and inpainting.
- Added detailed configuration files for model training and inference, including parameters for learning rates, model architectures, and data handling.
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds a valid_path helper function to folder_paths.py that validates whether a configured directory exists, attempts to resolve it via a JSON redirect file, or interactively prompts the user for a path and persists the mapping. base_path, models_dir, and output_directory are now derived through this helper instead of being set directly. Additionally, models_dir now joins base_path with "model" instead of the previous "models".

Changes

File Summary
folder_paths.py Added json import and valid_path() helper; base_path, models_dir, and output_directory now derived via valid_path(); models_dir folder name changed from "models" to "model".

Sequence Diagram(s)

sequenceDiagram
  participant Startup as folder_paths.py
  participant FS as Filesystem
  participant RedirectFile as JSON Redirect File
  participant User

  Startup->>FS: check if raw_path exists
  alt path exists
    FS-->>Startup: exists
  else path missing
    Startup->>RedirectFile: read redirect mapping
    alt redirect found
      RedirectFile-->>Startup: resolved path
    else no redirect
      Startup->>User: prompt for absolute path
      User-->>Startup: provided path
      Startup->>RedirectFile: write redirect mapping
    end
  end
  Startup-->>Startup: return base_path / models_dir / output_directory
Loading

Related issues: None linked in the provided context.

Suggested labels: enhancement, needs discussion

Suggested reviewers: None identified from available context.

Note: the change of models_dir from "models" to "model" alters the default models directory name, which may break existing installations relying on the prior default path. Also, valid_path swallowing exceptions when writing the redirect file could silently hide I/O failures.

Poem

A rabbit hopped through folders deep,
Where paths once lost were fixed asleep,
"Where art thou, model?" it did ask,
A JSON note fulfilled the task,
Now every directory found its keep. 🐇📁

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is broadly aligned with the PR, which does refactor model directory handling, though it omits the path-validation changes.
Description check ✅ Passed The description is related to the PR’s model directory/configuration work and is not off-topic.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@folder_paths.py`:
- Around line 21-48: `valid_path` currently prompts with `input()` during module
import, which can block or fail in non-interactive environments. Refactor
`valid_path` and the import-time assignments for `base_path`/`models_dir` to
avoid any stdin prompt at import; instead, return a fallback or raise a clear
non-interactive error, and move path resolution/creation behind an explicit
setup step or guard.
- Line 48: The models directory path in folder_paths.py was changed to the
singular form, which breaks the expected folder layout and downstream tests.
Update the models_dir assignment to use the existing plural directory name in
the path-building logic inside folder_paths.py, keeping it consistent with the
rest of the model subfolder handling and the expectations in folder path tests.
- Around line 25-42: Fix the redirect persistence logic in folder_paths.py: the
redirect loading/saving path handling is using the wrong variables and can fail
silently. In the redirect branch, use the redirect_path variable when opening
the JSON file instead of the string literal, and in the persistence block
replace the dict-vs-path mixups so os.path.exists and open operate on the
redirect file path, not the redirects dictionary. Keep the behavior centered
around the existing redirect_path, redirects, and new_path flow, and ensure the
redirect mapping is actually read and written successfully.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e3d614fa-82ef-432d-ba23-dea8759e93d6

📥 Commits

Reviewing files that changed from the base of the PR and between 6c62ca0 and 5b01fd4.

📒 Files selected for processing (37)
  • folder_paths.py
  • model/audio_encoders/put_audio_encoder_models_here
  • model/background_removal/put_background_removal_models_here
  • model/checkpoints/put_checkpoints_here
  • model/clip/put_clip_or_text_encoder_models_here
  • model/clip_vision/put_clip_vision_models_here
  • model/configs/anything_v3.yaml
  • model/configs/v1-inference.yaml
  • model/configs/v1-inference_clip_skip_2.yaml
  • model/configs/v1-inference_clip_skip_2_fp16.yaml
  • model/configs/v1-inference_fp16.yaml
  • model/configs/v1-inpainting-inference.yaml
  • model/configs/v2-inference-v.yaml
  • model/configs/v2-inference-v_fp32.yaml
  • model/configs/v2-inference.yaml
  • model/configs/v2-inference_fp32.yaml
  • model/configs/v2-inpainting-inference.yaml
  • model/controlnet/put_controlnets_and_t2i_here
  • model/detection/put_detection_models_here
  • model/diffusers/put_diffusers_models_here
  • model/diffusion_models/put_diffusion_model_files_here
  • model/embeddings/put_embeddings_or_textual_inversion_concepts_here
  • model/frame_interpolation/put_frame_interpolation_models_here
  • model/geometry_estimation/put_geometry_estimation_models_here
  • model/gligen/put_gligen_models_here
  • model/hypernetworks/put_hypernetworks_here
  • model/latent_upscale_models/put_latent_upscale_models_here
  • model/loras/put_loras_here
  • model/model_patches/put_model_patches_here
  • model/optical_flow/put_optical_flow_models_here
  • model/photomaker/put_photomaker_models_here
  • model/style_models/put_t2i_style_model_here
  • model/text_encoders/put_text_encoder_files_here
  • model/unet/put_unet_files_here
  • model/upscale_models/put_esrgan_and_other_upscale_models_here
  • model/vae/put_vae_here
  • model/vae_approx/put_taesd_encoder_pth_and_taesd_decoder_pth_here

Comment thread folder_paths.py
Comment on lines +21 to +48
def valid_path(saved_path,description = "Instance Folder"):
if os.path.exists(saved_path):
return saved_path

redirect_path = os.path.join(os.path.dirname(__file__),"path.redirects.json")
if os.path.exists(redirect_path):
with open("redirect_path","r") as f:
redirects = json.load(f)
if description in redirects and os.path.exists(redirects[description]):
return redirects[description]
print(f"\n[!] ALERT: {description} not found at: {saved_path}")
new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()
try:
redirects = {}
if os.path.exists(redirects):
with open(redirects, "r") as f: redirects = json.load(f)
redirects[description] = new_path
with open(redirects, "w") as f: json.dump(redirects, f, indent=4)
except Exception:
pass

return new_path

models_dir = os.path.join(base_path, "models")


base_path = valid_path(raw_path,description = "ComfyUI Core Directory")

models_dir =valid_path( os.path.join(base_path,"model"),description = "Model Directory")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift

valid_path calls input() at module import — this will hang headless/server/CI startup.

valid_path runs at import time for base_path, models_dir, and output_directory. On a fresh install these directories usually don't exist yet, so the code drops into input(...) and blocks on stdin. In a non-interactive context (systemd service, Docker, CI, the unit tests above) there's no TTY, so this either hangs forever or raises EOFError, preventing folder_paths from importing at all. Directory creation/validation shouldn't gate module import behind an interactive prompt.

🧰 Tools
🪛 ast-grep (0.44.0)

[warning] 35-35: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(redirects, "r")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)


[warning] 37-37: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(redirects, "w")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@folder_paths.py` around lines 21 - 48, `valid_path` currently prompts with
`input()` during module import, which can block or fail in non-interactive
environments. Refactor `valid_path` and the import-time assignments for
`base_path`/`models_dir` to avoid any stdin prompt at import; instead, return a
fallback or raise a clear non-interactive error, and move path
resolution/creation behind an explicit setup step or guard.

Comment thread folder_paths.py
Comment on lines +25 to +42
redirect_path = os.path.join(os.path.dirname(__file__),"path.redirects.json")
if os.path.exists(redirect_path):
with open("redirect_path","r") as f:
redirects = json.load(f)
if description in redirects and os.path.exists(redirects[description]):
return redirects[description]
print(f"\n[!] ALERT: {description} not found at: {saved_path}")
new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()
try:
redirects = {}
if os.path.exists(redirects):
with open(redirects, "r") as f: redirects = json.load(f)
redirects[description] = new_path
with open(redirects, "w") as f: json.dump(redirects, f, indent=4)
except Exception:
pass

return new_path

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

The redirect-file plumbing is riddled with wrong variables — it can crash and never persists.

Three concrete bugs in the redirect logic:

  • Line 27 opens the string literal "redirect_path" instead of the redirect_path variable, so whenever the real JSON file exists this raises FileNotFoundError (and it's not inside the try).
  • Lines 35, 36, 38 pass the redirects dict ({}) to os.path.exists/open where the path is expected. os.path.exists({}) raises TypeError, which the bare except Exception: pass silently swallows, so the mapping is never written.

Net effect: the redirect file is never read correctly and never saved.

🐛 Proposed fix
     redirect_path = os.path.join(os.path.dirname(__file__),"path.redirects.json")
     if os.path.exists(redirect_path):
-        with open("redirect_path","r") as f:
+        with open(redirect_path,"r") as f:
             redirects = json.load(f)
             if description in redirects and os.path.exists(redirects[description]):
                 return redirects[description]
     print(f"\n[!] ALERT: {description} not found at: {saved_path}")
     new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()
     try:
         redirects = {}
-        if os.path.exists(redirects):
-            with open(redirects, "r") as f: redirects = json.load(f)
+        if os.path.exists(redirect_path):
+            with open(redirect_path, "r") as f: redirects = json.load(f)
         redirects[description] = new_path
-        with open(redirects, "w") as f: json.dump(redirects, f, indent=4)
+        with open(redirect_path, "w") as f: json.dump(redirects, f, indent=4)
     except Exception:
         pass
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
redirect_path = os.path.join(os.path.dirname(__file__),"path.redirects.json")
if os.path.exists(redirect_path):
with open("redirect_path","r") as f:
redirects = json.load(f)
if description in redirects and os.path.exists(redirects[description]):
return redirects[description]
print(f"\n[!] ALERT: {description} not found at: {saved_path}")
new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()
try:
redirects = {}
if os.path.exists(redirects):
with open(redirects, "r") as f: redirects = json.load(f)
redirects[description] = new_path
with open(redirects, "w") as f: json.dump(redirects, f, indent=4)
except Exception:
pass
return new_path
redirect_path = os.path.join(os.path.dirname(__file__),"path.redirects.json")
if os.path.exists(redirect_path):
with open(redirect_path,"r") as f:
redirects = json.load(f)
if description in redirects and os.path.exists(redirects[description]):
return redirects[description]
print(f"\n[!] ALERT: {description} not found at: {saved_path}")
new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()
try:
redirects = {}
if os.path.exists(redirect_path):
with open(redirect_path, "r") as f: redirects = json.load(f)
redirects[description] = new_path
with open(redirect_path, "w") as f: json.dump(redirects, f, indent=4)
except Exception:
pass
return new_path
🧰 Tools
🪛 ast-grep (0.44.0)

[warning] 35-35: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(redirects, "r")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)


[warning] 37-37: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(redirects, "w")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@folder_paths.py` around lines 25 - 42, Fix the redirect persistence logic in
folder_paths.py: the redirect loading/saving path handling is using the wrong
variables and can fail silently. In the redirect branch, use the redirect_path
variable when opening the JSON file instead of the string literal, and in the
persistence block replace the dict-vs-path mixups so os.path.exists and open
operate on the redirect file path, not the redirects dictionary. Keep the
behavior centered around the existing redirect_path, redirects, and new_path
flow, and ensure the redirect mapping is actually read and written successfully.

Comment thread folder_paths.py

base_path = valid_path(raw_path,description = "ComfyUI Core Directory")

models_dir =valid_path( os.path.join(base_path,"model"),description = "Model Directory")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

models_dir now points at base_path/model — this breaks the established layout.

The directory has always been models (plural), and every model subfolder plus the downstream test in tests-unit/comfy_test/folder_path_test.py expects os.path.join(base_path, "models"). Dropping the s will make ComfyUI look for models in a nonexistent directory (and, combined with valid_path, trigger the interactive prompt on startup).

🐛 Proposed fix
-models_dir =valid_path( os.path.join(base_path,"model"),description = "Model Directory")
+models_dir = valid_path(os.path.join(base_path, "models"), description="Model Directory")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
models_dir =valid_path( os.path.join(base_path,"model"),description = "Model Directory")
models_dir = valid_path(os.path.join(base_path, "models"), description="Model Directory")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@folder_paths.py` at line 48, The models directory path in folder_paths.py was
changed to the singular form, which breaks the expected folder layout and
downstream tests. Update the models_dir assignment to use the existing plural
directory name in the path-building logic inside folder_paths.py, keeping it
consistent with the rest of the model subfolder handling and the expectations in
folder path tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

How come we can't relocate instances?

1 participant