Skip to content

Fix/dynamic path relocation#14769

Open
Samith-NM wants to merge 3 commits into
Comfy-Org:masterfrom
Samith-NM:fix/dynamic-path-relocation
Open

Fix/dynamic path relocation#14769
Samith-NM wants to merge 3 commits into
Comfy-Org:masterfrom
Samith-NM:fix/dynamic-path-relocation

Conversation

@Samith-NM

Copy link
Copy Markdown

Description

This PR resolves the issue where missing or moved core model/instance directories cause the application to crash or drop into unhandled exception loops during initialization.

Changes

  • Wrapped directory path checks with a get_notes_path or get_valid_path helper function.
  • Catches instances where directories are missing, preventing hard crashes and offering a clean validation step.

#14760 Fixes
Closes #14760

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e4997ce1-bf06-475f-a5c9-95c21659d35b

📥 Commits

Reviewing files that changed from the base of the PR and between a2b56d8 and 3c3d7fe.

📒 Files selected for processing (1)
  • folder_paths.py

📝 Walkthrough

Walkthrough

Changes

folder_paths.py adds valid_path() to resolve paths by checking whether a saved path exists, loading a redirect from path.redirects.json when present, or prompting for a replacement path and saving it back to that JSON file. base_path, models_dir, and output_directory now use this helper instead of direct path construction.

Sequence Diagram(s)

Not applicable.

Compact Metadata
Type: Enhancement
Impact Scope: folder_paths.py

Related PRs: None identified
Related Issues: None identified

Suggested Labels: enhancement, needs-review

Suggested Reviewers: None identified

Poem
Paths now ask before they stray,
Redirects guide the safer way,
If missing, prompt and save the trace,
Then folders land in the right place.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and matches the main change: dynamic path relocation handling.
Description check ✅ Passed The description is clearly related to the path-relocation and initialization-failure fix.
Linked Issues check ✅ Passed The changes add redirect and validation behavior for moved instance/model paths, addressing #14760's relocation failure.
Out of Scope Changes check ✅ Passed The diff appears confined to path validation and relocation handling in folder_paths.py with no unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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: 4

🤖 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 31-32: Module import should not block on interactive path recovery
in valid_path(). Move the relocation flow out of folder_paths.py import-time
logic so valid_path(), and the callers for base/model/output paths, do not call
input() during import; instead use an explicit recovery/validation step or raise
a clear exception when a path is missing. Update the logic around valid_path and
any related path initialization helpers so they fail fast or are invoked only
from an interactive entrypoint.
- Line 91: The default output path in folder_paths.py is being treated as if it
must already exist, which blocks fresh setups. Update the output_directory
initialization around valid_path(os.path.join(base_path, "output"), "Output
Directory") so the default <base>/output is created or accepted when missing,
while still keeping validation behavior for relocated existing roots. Use the
existing output_directory and valid_path flow to ensure downstream callers
always get a writable destination without prompting for the default case.
- Around line 33-40: The redirect persistence logic in `folder_paths` is using
the `redirects` dictionary where it should use `redirect_path`, so
`os.path.exists()` and the file open calls fail before any data is saved. Update
the load/write flow to check and read from `redirect_path`, then persist
`description -> new_path` back to that same path. In the same block, replace the
broad `except Exception` with specific expected IO/JSON handling so the failure
is not silently swallowed.
- Around line 29-42: The path recovery logic in folder_paths should validate
both the stored redirect and the user-entered new_path before returning them.
Update the redirect lookup/entry flow to ensure the resolved path is absolute,
exists, and is a directory before assigning it for base_path, models_dir, or
output_directory, and raise a clear error instead of silently returning an
invalid path. Use the existing redirect handling block and new_path prompt flow
to locate the fix.
🪄 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: 7e89dc48-b69e-44d9-bf3f-606b6a712311

📥 Commits

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

📒 Files selected for processing (1)
  • folder_paths.py

Comment thread folder_paths.py
Comment on lines +29 to +42
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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Validate redirected and entered paths before returning them.

Both stored redirects and new_path are returned without enforcing absolute path, existence, or directory-ness. That can leave base_path, models_dir, or output_directory pointing at an empty/relative/nonexistent path after the “recovery” flow.

Proposed guard
-            if description in redirects and os.path.exists(redirects[description]):
-                return redirects[description]
+            redirected_path = redirects.get(description)
+            if redirected_path and os.path.isabs(redirected_path) and os.path.isdir(redirected_path):
+                return redirected_path
...
-    new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()        
+    new_path = input(f"Please paste the updated absolute path for '{description}': ").strip()
+    if not os.path.isabs(new_path) or not os.path.isdir(new_path):
+        raise FileNotFoundError(f"{description} must be an existing absolute directory: {new_path}")

As per coding guidelines, unsupported paths and bad states should fail with clear errors instead of silently producing worse behavior.

📝 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
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
redirected_path = redirects.get(description)
if redirected_path and os.path.isabs(redirected_path) and os.path.isdir(redirected_path):
return redirected_path
print(f"\n[!] ALERT: {description} not found at: {saved_path}")
new_path = input(f"Please paste the updated absolute path for '{description}': ").strip()
if not os.path.isabs(new_path) or not os.path.isdir(new_path):
raise FileNotFoundError(f"{description} must be an existing absolute directory: {new_path}")
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
🧰 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 29 - 42, The path recovery logic in
folder_paths should validate both the stored redirect and the user-entered
new_path before returning them. Update the redirect lookup/entry flow to ensure
the resolved path is absolute, exists, and is a directory before assigning it
for base_path, models_dir, or output_directory, and raise a clear error instead
of silently returning an invalid path. Use the existing redirect handling block
and new_path prompt flow to locate the fix.

Source: Coding guidelines

Comment thread folder_paths.py
Comment on lines +31 to +32
print(f"\n[!] ALERT: {description} not found at: {saved_path}")
new_path= input(f"Please paste the updated absolute path for '{description}': ").strip()

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 | 🟠 Major | ⚡ Quick win

Avoid prompting from module import.

valid_path() is called while folder_paths.py imports, so a missing base/model/output directory can block indefinitely or raise EOFError in headless startup. Route relocation through an explicit validation/recovery step, or fail with a clear exception instead of calling input() here.

Also applies to: 46-48, 91-91

🤖 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 31 - 32, Module import should not block on
interactive path recovery in valid_path(). Move the relocation flow out of
folder_paths.py import-time logic so valid_path(), and the callers for
base/model/output paths, do not call input() during import; instead use an
explicit recovery/validation step or raise a clear exception when a path is
missing. Update the logic around valid_path and any related path initialization
helpers so they fail fast or are invoked only from an interactive entrypoint.

Comment thread folder_paths.py Outdated
Comment thread folder_paths.py
folder_names_and_paths["detection"] = ([os.path.join(models_dir, "detection")], supported_pt_extensions)

output_directory = os.path.join(base_path, "output")
output_directory =valid_path( os.path.join(base_path, "output"),"Output 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 | 🟠 Major | ⚡ Quick win

Don’t require the default output directory to pre-exist.

output_directory is a writable destination; prompting when <base>/output is missing breaks fresh or relocated instances where the directory can be created. Keep validation for relocated existing roots, but create or tolerate the default output directory before downstream callers use it.

Proposed adjustment
-output_directory =valid_path( os.path.join(base_path, "output"),"Output Directory")
+output_directory = os.path.join(base_path, "output")
+os.makedirs(output_directory, exist_ok=True)
📝 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
output_directory =valid_path( os.path.join(base_path, "output"),"Output Directory")
output_directory = os.path.join(base_path, "output")
os.makedirs(output_directory, exist_ok=True)
🤖 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 91, The default output path in folder_paths.py is
being treated as if it must already exist, which blocks fresh setups. Update the
output_directory initialization around valid_path(os.path.join(base_path,
"output"), "Output Directory") so the default <base>/output is created or
accepted when missing, while still keeping validation behavior for relocated
existing roots. Use the existing output_directory and valid_path flow to ensure
downstream callers always get a writable destination without prompting for the
default case.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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