Fix default database path for custom user directory - #14539
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthrough
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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. Comment |
374bb9a to
9789de0
Compare
|
Rebased this PR on the latest master and re-ran the related checks:
|
|
@guill @alexisrolland Hi, sorry for the ping — would either of you have a moment to take a look at this one? It fixes #14524 (the DB ending up in the install dir when --user-directory / --base-directory is set). CI is green and it's rebased on latest master. Happy to rework the approach if you'd prefer something different. |
|
Looping in @mattmillerai and @synap5e who have been working in this space recently and may have opinions. |
|
Thanks @guill. @mattmillerai @synap5e — the gist is: default DB follows |
synap5e
left a comment
There was a problem hiding this comment.
Thanks for this, agree the database should respect user dir and would want to merge a fix.
The overall approach is good: resolving the default lazily at init time (after apply_custom_paths() has run).
Couple of things to address.
1. database-url argument handling
Scanning sys.argv misses cases argparse itself handles (e.g. --database-u "abbreviated args") and regresses programmatic use + introduces a refactoring hazard.
Instead, I'd rather we use default=None on --database-url and treat args.database_url is not None as explicit at resolution time - probably mention the fallback in the help text. This is consistent with other path args (--user-directory, --output-directory), and removes the argv scan and the database_url_explicit attribute. database_default_path in cli_args.py then stops being the argparse default and can serve as the legacy path for the copy, instead of parsing it back out of a URL string.
Keeping args.database_url populated for compatibility: I'm concerned this is a footgun rather than a feature. Whenever this fix matters (custom user dir in effect), args.database_url holds a path the DB is not actually at, so anything reading it gets misled. None plus db.get_database_url() as the accessor would be preferred.
2. Legacy copy semantics
Copying preserves user-authored DB state, which feels correct, but it leaves two databases behind. Launch once more without --user-directory and you are silently back on an old diverged install-dir copy.
@guill what are your thoughts here?
I'm inclined to say lets keep as this PR proposes, it since that hazard is less bad than appearing to lose data.
Smaller notes
- Parent directories are now auto-created for explicit
--database-urlvalues too, where before a missing parent failed at startup. Agree with this fix, just state it in the PR description as intentional. - Tests: worth adding a regression test that with no flags
get_db_path()resolves to the same<install>/user/comfyui.dbas before, and one that an explicit URL pointing at the old default location is honoured verbatim with no copy.
Per review: default --database-url to None and treat a non-None value as explicit at resolution time. Removes the sys.argv scan and the database_url_explicit attribute. database_default_path now serves directly as the legacy copy source. Adds regression tests for the unchanged no-flag default path and explicit URLs at the legacy location.
|
✅ All contributors have signed the CLA. Thank you! This PR is ready to be merged. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/database/db.py (1)
65-72: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winHoist the database-path imports to module scope.
import folder_pathsandfrom comfy.cli_args import database_default_pathare only used in these helpers, andfolder_paths.pydoesn’t importapp.database.db, so there’s no cycle preventing the move.🤖 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 `@app/database/db.py` around lines 65 - 72, Move the folder_paths and database_default_path imports out of the get_database_url helper and into module scope, then reuse those module-level symbols in the helper. Preserve the existing database URL selection and fallback path behavior.Source: Coding guidelines
🤖 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.
Outside diff comments:
In `@app/database/db.py`:
- Around line 65-72: Move the folder_paths and database_default_path imports out
of the get_database_url helper and into module scope, then reuse those
module-level symbols in the helper. Preserve the existing database URL selection
and fallback path behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: c56fa556-65ef-4926-b230-25ee36b46778
📒 Files selected for processing (3)
app/database/db.pycomfy/cli_args.pytests-unit/app_test/database_path_test.py
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: CodeRabbit
⚠️ CI failures not shown inline (2)
GitHub Actions: CLA Assistant / 0_cla-assistant.txt: Fix default database path for custom user directory
Conclusion: failure
##[group]Run contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08
with:
path-to-document: https://github.com/Comfy-Org/comfy-cla/blob/main/comfyui_icla.md
remote-organization-name: comfy-org
remote-repository-name: comfy-cla
path-to-signatures: signatures/cla.json
branch: main
allowlist: action@github.com,actions-user,ampagent,claude,comfy-pr-bot,GitHub Action,github-actions,github-actions[bot],Glary Bot,Glary-Bot,*[bot]
custom-notsigned-prcomment: 🎉 Thank you for your contribution, we really appreciate it! 🎉
Like many open source projects, we require contributors to sign our [Contributor License Agreement (CLA)](https://github.com/Comfy-Org/comfy-cla/blob/main/comfyui_icla.md). A CLA makes the ownership of contributions explicit, so contributors and the project share a clear understanding of how the code can be used. By signing, you:
- Confirm that you own your contribution.
- Keep the right to reuse your own code.
- Grant us a copyright license to include and share it within our projects.
CLAs are standard practice across major open source projects including those under the Apache Software Foundation and the Linux Foundation. Ours is based on the Apache Software Foundation's CLA. Most importantly, it would enable us to relicense the project under a more permissive license in the future, giving the project and its community greater flexibility.
✍ **To sign, please post a new comment on this PR with exactly the following text:** ✍
custom-pr-sign-comment: I have read and agree to the Contributor License Agreement
custom-allsigned-prcomment: ✅ All contributors have signed the CLA. Thank you! This PR is ready to be merged.
use-dco-flag: false
lock-pullrequest-aftermerge: true
suggest-recheck: true
env:
GITHUB_***REDACTED***
PERSONAL_ACCESS_***REDACTED***
##[endgroup]
CLA Assistant GitHub Action bot has started the process
(node:2112) [DEP0040] DeprecationWarning: The `punycode` module is deprec...
GitHub Actions: CLA Assistant / cla-assistant: Fix default database path for custom user directory
Conclusion: failure
##[group]Run contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08
with:
path-to-document: https://github.com/Comfy-Org/comfy-cla/blob/main/comfyui_icla.md
remote-organization-name: comfy-org
remote-repository-name: comfy-cla
path-to-signatures: signatures/cla.json
branch: main
allowlist: action@github.com,actions-user,ampagent,claude,comfy-pr-bot,GitHub Action,github-actions,github-actions[bot],Glary Bot,Glary-Bot,*[bot]
custom-notsigned-prcomment: 🎉 Thank you for your contribution, we really appreciate it! 🎉
Like many open source projects, we require contributors to sign our [Contributor License Agreement (CLA)](https://github.com/Comfy-Org/comfy-cla/blob/main/comfyui_icla.md). A CLA makes the ownership of contributions explicit, so contributors and the project share a clear understanding of how the code can be used. By signing, you:
- Confirm that you own your contribution.
- Keep the right to reuse your own code.
- Grant us a copyright license to include and share it within our projects.
CLAs are standard practice across major open source projects including those under the Apache Software Foundation and the Linux Foundation. Ours is based on the Apache Software Foundation's CLA. Most importantly, it would enable us to relicense the project under a more permissive license in the future, giving the project and its community greater flexibility.
✍ **To sign, please post a new comment on this PR with exactly the following text:** ✍
custom-pr-sign-comment: I have read and agree to the Contributor License Agreement
custom-allsigned-prcomment: ✅ All contributors have signed the CLA. Thank you! This PR is ready to be merged.
use-dco-flag: false
lock-pullrequest-aftermerge: true
suggest-recheck: true
env:
GITHUB_***REDACTED***
PERSONAL_ACCESS_***REDACTED***
##[endgroup]
CLA Assistant GitHub Action bot has started the process
(node:2112) [DEP0040] DeprecationWarning: The `punycode` module is deprec...
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Keep imports at module scope; avoid inline imports unless they are already part of an established optional-backend probe or are needed to avoid an import cycle.
Do not add unnecessarytry/exceptblocks; use them for optional dependency, platform, or backend capability detection only when the program has a useful fallback, and prefer specific exception types when changing new code.
If a library version is pinned inrequirements.txt, do not add code to ComfyUI to handle older versions of that library.
Remove any workarounds for PyTorch versions that ComfyUI no longer officially supports; deprecated workarounds include catching an exception and rerunning the same op with the input cast to float unless the code comments name the exact supported PyTorch versions.
Let unsupported model formats, invalid quantization metadata, and bad states fail with clear errors instead of silently producing lower quality output.
Match the existing local style in the file you edit; long lines, simple helper functions, module-level state, and direct tensor operations are acceptable when they make the code easier to follow.
Keep comments sparse and useful; strip comments that restate the code or describe obvious behavior, and keep short TODOs only when they name the concrete missing follow-up.
Treat dtype, device placement, VRAM usage, and offloading behavior as core correctness concerns; check CPU, CUDA, ROCm, MPS, DirectML, XPU, NPU, and low-VRAM implications when touching shared execution or loading code.
Prefer native ComfyUI formats and existing quantization/offload helpers over adding parallel code paths; usecomfy.quant_ops,comfy.model_management,comfy.memory_management,comfy.pinned_memory,comfy_aimdo, andcomfy-kitchenhelpers where they already solve the problem.
Use optimized comfy-kitchen ops in places where they improve performance without changing the expected dtype, device, memory, or interface behavior.
All models should use the optimized atte...
Files:
app/database/db.pycomfy/cli_args.pytests-unit/app_test/database_path_test.py
**
⚙️ CodeRabbit configuration file
**: IMPORTANT: Only comment on issues directly introduced by this PR's code changes.
Treat AGENTS.md as mandatory repository policy, not optional style guidance.
Flag PR changes that violate AGENTS.md even when the code is otherwise functional.
In particular, enforce architecture boundaries, dtype/device/memory rules,
interface contracts, import style, no unnecessary try/except blocks, no inline
imports, no outbound internet paths in core ComfyUI, and narrow scoped fixes.
Prefer direct findings over suggestions when a rule is violated. Only ignore
AGENTS.md when it clearly conflicts with a newer explicit maintainer instruction
in the PR.
Do NOT flag pre-existing issues in code that was merely moved, re-indented,
de-indented, or reformatted without logic changes. If code appears in the diff
only due to whitespace or structural reformatting (e.g., removing awith:block),
treat it as unchanged. Contributors should not feel obligated to address
pre-existing issues outside the scope of their contribution.
Files:
app/database/db.pycomfy/cli_args.pytests-unit/app_test/database_path_test.py
comfy/**
⚙️ CodeRabbit configuration file
comfy/**: Core ML/diffusion engine. Focus on:
- Backward compatibility (breaking changes affect all custom nodes)
- Memory management and GPU resource handling
- Performance implications in hot paths
- Thread safety for concurrent execution
Files:
comfy/cli_args.py
🧠 Learnings (2)
📚 Learning: 2026-02-21T14:01:41.482Z
Learnt from: pythongosssss
Repo: Comfy-Org/ComfyUI PR: 12555
File: comfy_extras/nodes_glsl.py:719-724
Timestamp: 2026-02-21T14:01:41.482Z
Learning: In PyOpenGL, bare Python scalars can be accepted for 1-element array parameters by NumberHandler. This means you can pass an int/float directly to OpenGL texture deletion (e.g., glDeleteTextures(tex)) without wrapping in a list. Verify function-specific expectations and ensure types match what the OpenGL call expects; use explicit lists only when the API requires an array.
Applied to files:
app/database/db.pycomfy/cli_args.pytests-unit/app_test/database_path_test.py
📚 Learning: 2026-05-13T12:31:45.069Z
Learnt from: rattus128
Repo: Comfy-Org/ComfyUI PR: 13802
File: comfy/pinned_memory.py:19-30
Timestamp: 2026-05-13T12:31:45.069Z
Learning: When reviewing code that uses comfy/pinned_memory.py’s `HostBuffer.extend(size=..., reallocate=...)`: by default (`reallocate` is not True / False), `extend(size=...)` is a *relative increment* that grows the buffer by `size` bytes—so slicing like `[offset:offset+size]` after `hostbuf.extend(size=size)` is correct and the argument should not be rewritten to `offset + size`. Only in the single-segment reallocation mode (`reallocate=True`, e.g., as used by `resize_pin_buffer()` in `comfy/model_management.py`) should `size` be treated as an *absolute target* and the call/arguments should be checked accordingly.
Applied to files:
comfy/cli_args.py
🔇 Additional comments (4)
comfy/cli_args.py (1)
241-241: LGTM!app/database/db.py (2)
89-104: LGTM!The copy logic is well-guarded: skips on explicit URL, avoids self-copy via
abspathcomparison, and preserves existing target DB. The ordering in_init_file_db(prepare → existence check) correctly ensures a copied legacy DB is detected for incremental migration.
142-142: LGTM!Using
get_database_url()ininit_db()and callingprepare_file_db_path()before the existence check in_init_file_db()are both correct changes.Also applies to: 179-179
tests-unit/app_test/database_path_test.py (1)
1-114: LGTM!Tests are thorough — covering default URL resolution, explicit URL preservation, legacy copy (skip/copy/no-overwrite), directory creation, and relative path handling. Assertions align with the implementation in
db.py.
|
I have read and agree to the Contributor License Agreement |
|
Thanks for the detailed review @synap5e — all fair points. Pushed the rework: |
I think the standard solution for this is to rename the original database to |
Per review: after copying the legacy install-dir database to the effective user directory, rename the original to comfyui.db.bak so a later launch without --user-directory cannot silently fall back to a diverged copy, while keeping the file around for recovery. Also hoist the database_default_path import to module scope.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/database/db.py (1)
87-105: 🗄️ Data Integrity & Integration | 🔴 Critical | 🏗️ Heavy liftData corruption and divergence risks during legacy database migration.
This migration logic has critical concurrency and atomicity flaws that can lead to database corruption, silent data divergence, or startup crashes:
- Legacy DB in use: If an existing ComfyUI process is actively using
legacy_db_path, it will be renamed while in use. On Windows,os.replacewill raise aPermissionErrorand crash. On Linux/macOS, the old process will continue writing to the.bakfile while the new process uses the copied database, silently splitting user data across two files.- Migration Race Condition (TOCTOU): If multiple instances start simultaneously with the same new
db_path, they will race to copy and rename the file. This can lead to concurrentshutil.copywrites (corrupting the DB) or aFileNotFoundErrorduringos.replace.- Non-atomic Copy: If
shutil.copyfails midway (e.g., out of disk space or process killed), a partially writtendb_pathis left behind. On the next startup, it will skip the copy and attempt to load a corrupted SQLite file.- Symlink Crash: If the user symlinked the legacy directory to the new user directory to manage space,
os.path.abspathwon't detect they are the same file, causingshutil.copyto crash withshutil.SameFileError.Recommendation:
Acquire thelegacy_db_pathlock to ensure it's not in use, useos.path.realpathto resolve symlinks, perform the copy atomically via a temporary file, and ensure the caller (_init_file_db) has already acquired the lock fordb_path.🛡️ Proposed safe migration logic
def copy_legacy_default_db(db_path): if args.database_url is not None: return legacy_db_path = get_legacy_default_db_path() if legacy_db_path is None: return # Use realpath to avoid SameFileError if the user symlinked the directories if os.path.realpath(legacy_db_path) == os.path.realpath(db_path): return if os.path.exists(db_path) or not os.path.exists(legacy_db_path): return # 1. Ensure the legacy DB is not actively in use legacy_lock = FileLock(f"{legacy_db_path}.lock") try: legacy_lock.acquire(timeout=0) except Timeout: raise RuntimeError(f"Cannot migrate legacy database '{legacy_db_path}' because it is actively in use by another process.") try: # Note: The caller (_init_file_db) must acquire the lock for `db_path` BEFORE calling this function # to prevent multiple instances from racing to perform this migration. # 2. Perform copy atomically to prevent partial writes temp_db_path = f"{db_path}.tmp" shutil.copy(legacy_db_path, temp_db_path) # (Optional: copy -wal and -shm files here if WAL mode is heavily relied upon) os.replace(temp_db_path, db_path) os.replace(legacy_db_path, f"{legacy_db_path}.bak") logging.info( f"Copied legacy database from '{legacy_db_path}' to '{db_path}' and renamed the original to '{legacy_db_path}.bak'" ) finally: legacy_lock.release()🤖 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 `@app/database/db.py` around lines 87 - 105, Update copy_legacy_default_db to resolve both paths with os.path.realpath, acquire and release a non-blocking FileLock for the legacy database, and fail clearly when it is in use. Ensure _init_file_db acquires the destination db_path lock before calling this function, then copy to a temporary path and atomically replace the destination before renaming the legacy file; preserve existing early-return conditions and clean up temporary files on failure.
🤖 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.
Outside diff comments:
In `@app/database/db.py`:
- Around line 87-105: Update copy_legacy_default_db to resolve both paths with
os.path.realpath, acquire and release a non-blocking FileLock for the legacy
database, and fail clearly when it is in use. Ensure _init_file_db acquires the
destination db_path lock before calling this function, then copy to a temporary
path and atomically replace the destination before renaming the legacy file;
preserve existing early-return conditions and clean up temporary files on
failure.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 7a0b8878-d756-450d-87a8-dc97d27b7899
📒 Files selected for processing (2)
app/database/db.pytests-unit/app_test/database_path_test.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Keep imports at module scope; avoid inline imports unless they are already part of an established optional-backend probe or are needed to avoid an import cycle.
Do not add unnecessarytry/exceptblocks; use them for optional dependency, platform, or backend capability detection only when the program has a useful fallback, and prefer specific exception types when changing new code.
If a library version is pinned inrequirements.txt, do not add code to ComfyUI to handle older versions of that library.
Remove any workarounds for PyTorch versions that ComfyUI no longer officially supports; deprecated workarounds include catching an exception and rerunning the same op with the input cast to float unless the code comments name the exact supported PyTorch versions.
Let unsupported model formats, invalid quantization metadata, and bad states fail with clear errors instead of silently producing lower quality output.
Match the existing local style in the file you edit; long lines, simple helper functions, module-level state, and direct tensor operations are acceptable when they make the code easier to follow.
Keep comments sparse and useful; strip comments that restate the code or describe obvious behavior, and keep short TODOs only when they name the concrete missing follow-up.
Treat dtype, device placement, VRAM usage, and offloading behavior as core correctness concerns; check CPU, CUDA, ROCm, MPS, DirectML, XPU, NPU, and low-VRAM implications when touching shared execution or loading code.
Prefer native ComfyUI formats and existing quantization/offload helpers over adding parallel code paths; usecomfy.quant_ops,comfy.model_management,comfy.memory_management,comfy.pinned_memory,comfy_aimdo, andcomfy-kitchenhelpers where they already solve the problem.
Use optimized comfy-kitchen ops in places where they improve performance without changing the expected dtype, device, memory, or interface behavior.
All models should use the optimized atte...
Files:
tests-unit/app_test/database_path_test.pyapp/database/db.py
**
⚙️ CodeRabbit configuration file
**: IMPORTANT: Only comment on issues directly introduced by this PR's code changes.
Treat AGENTS.md as mandatory repository policy, not optional style guidance.
Flag PR changes that violate AGENTS.md even when the code is otherwise functional.
In particular, enforce architecture boundaries, dtype/device/memory rules,
interface contracts, import style, no unnecessary try/except blocks, no inline
imports, no outbound internet paths in core ComfyUI, and narrow scoped fixes.
Prefer direct findings over suggestions when a rule is violated. Only ignore
AGENTS.md when it clearly conflicts with a newer explicit maintainer instruction
in the PR.
Do NOT flag pre-existing issues in code that was merely moved, re-indented,
de-indented, or reformatted without logic changes. If code appears in the diff
only due to whitespace or structural reformatting (e.g., removing awith:block),
treat it as unchanged. Contributors should not feel obligated to address
pre-existing issues outside the scope of their contribution.
Files:
tests-unit/app_test/database_path_test.pyapp/database/db.py
🧠 Learnings (1)
📚 Learning: 2026-02-21T14:01:41.482Z
Learnt from: pythongosssss
Repo: Comfy-Org/ComfyUI PR: 12555
File: comfy_extras/nodes_glsl.py:719-724
Timestamp: 2026-02-21T14:01:41.482Z
Learning: In PyOpenGL, bare Python scalars can be accepted for 1-element array parameters by NumberHandler. This means you can pass an int/float directly to OpenGL texture deletion (e.g., glDeleteTextures(tex)) without wrapping in a list. Verify function-specific expectations and ensure types match what the OpenGL call expects; use explicit lists only when the API requires an array.
Applied to files:
tests-unit/app_test/database_path_test.pyapp/database/db.py
🔇 Additional comments (1)
tests-unit/app_test/database_path_test.py (1)
75-76: LGTM!
|
Makes sense — done. The legacy DB is now renamed to |
| shutil.copy(legacy_db_path, db_path) | ||
| os.replace(legacy_db_path, legacy_db_path + ".bak") |
There was a problem hiding this comment.
If a user is running one comfyui with no user dir set and launches a second comfyui with an explicit user dir, the second instance could pick up the first's db as a "legacy" and try migrate it.
I think the cleanest fix would be add a guard on .bak existing and bail out of migration then. That way users can run arbitrary new --user-dir's and only the first-run would attempt to migrate. Minor ambiguity of intent on first run because we can't tell if they have always been using user-dir or if they want to create a fresh user dir, but not a blocker IMO.
Also I think cleaner to rename before copy - os.replace fails fast if another running instance holds the legacy DB open (at least on windows).
| shutil.copy(legacy_db_path, db_path) | |
| os.replace(legacy_db_path, legacy_db_path + ".bak") | |
| backup_path = legacy_db_path + ".bak" | |
| if os.path.exists(backup_path): | |
| return | |
| os.replace(legacy_db_path, backup_path) | |
| shutil.copy(backup_path, db_path) |
There was a problem hiding this comment.
Good catch on the two-instance scenario — applied your suggestion: bail out if .bak already exists, and rename before copy so os.replace fails fast if the legacy DB is held open. Added a test for the existing-.bak case.
Per review: bail out of the legacy migration when comfyui.db.bak already exists, so only the first run migrates and later launches with a fresh --user-directory cannot grab a database another instance is using. Rename before copy so os.replace fails fast if the legacy DB is held open by a running instance.
|
@synap5e thanks again for the approval! Is there anything else needed from my side to get this merged? Happy to rebase onto latest master if that helps. |
Fixes #14524
Summary
--database-urlnow defaults toNone; a non-Nonevalue is treated as explicit at resolution time and used verbatim.db.get_database_url()is the accessor for the effective URL.comfyui.db.bakso it stays available for recovery but cannot be silently loaded again.Notes
For users who did not explicitly pass
--database-urland use--user-directoryor--base-directory, the default DB location now follows the effective user directory. If an existing legacy install-directoryuser/comfyui.dbis present and the new target DB is missing, it is copied once to avoid appearing to lose existing asset data, and the original is renamed tocomfyui.db.bak.Intentional behavior change: parent directories of the database path are now created automatically, including for explicit
--database-urlvalues (previously a missing parent directory failed at startup).Testing
.venv/bin/python -m pytest tests-unit/app_test/test_migrations.py tests-unit/app_test/database_path_test.py -q.venv/bin/python -m ruff check .