From b369532116da8c44d18b31b265c05a41811b8b5a Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Tue, 30 Jun 2026 15:25:26 -0700 Subject: [PATCH] fix(assets): fail safe to 503 when DB unavailable; keep --enable-assets as no-op Address automated review feedback on the always-on assets change: - setup_database(): on DB init failure or missing dependencies, call disable_assets_routes() + asset_seeder.disable() so /api/assets/* returns a clean 503 instead of 500s against an uninitialized DB (restores the fail-safe the removed else-branch used to provide). - feature_flags: derive the advertised 'assets' capability from live backend availability instead of hardcoding True, so clients degrade gracefully. - cli_args: re-add --enable-assets as a hidden deprecated no-op so existing launchers still passing the flag don't abort argparse. - routes: add assets_enabled() accessor for the feature-flag derivation. --- app/assets/api/routes.py | 9 +++++++++ comfy/cli_args.py | 3 +++ comfy_api/feature_flags.py | 11 ++++++++++- main.py | 11 +++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/app/assets/api/routes.py b/app/assets/api/routes.py index dced93712..cde55ec02 100644 --- a/app/assets/api/routes.py +++ b/app/assets/api/routes.py @@ -102,6 +102,15 @@ def disable_assets_routes() -> None: _ASSETS_ENABLED = False +def assets_enabled() -> bool: + """Return whether the asset routes are currently serving requests. + + Reflects live backend availability: False once disable_assets_routes() has + been called (e.g. after a database init failure or missing dependencies). + """ + return _ASSETS_ENABLED + + def _build_error_response( status: int, code: str, message: str, details: dict | None = None ) -> web.Response: diff --git a/comfy/cli_args.py b/comfy/cli_args.py index 15dc0d04d..0c82fb8b8 100644 --- a/comfy/cli_args.py +++ b/comfy/cli_args.py @@ -239,6 +239,9 @@ database_default_path = os.path.abspath( os.path.join(os.path.dirname(__file__), "..", "user", "comfyui.db") ) parser.add_argument("--database-url", type=str, default=f"sqlite:///{database_default_path}", help="Specify the database URL, e.g. for an in-memory database you can use 'sqlite:///:memory:'.") +# Deprecated no-op: the asset system is now always enabled. Kept (hidden) so that +# existing launchers/containers still passing --enable-assets don't fail argparse. +parser.add_argument("--enable-assets", action="store_true", help=argparse.SUPPRESS) parser.add_argument("--enable-asset-hashing", action="store_true", help="Compute blake3 content hashes when scanning assets. Hashing enables future asset-portability features (deduplication, cross-machine model resolution) but adds startup cost and per-output cost on large models directories. Off by default; enable to opt in.") parser.add_argument("--feature-flag", type=str, action='append', default=[], metavar="KEY[=VALUE]", help="Set a server feature flag. Use KEY=VALUE to set an explicit value, or bare KEY to set it to true. Can be specified multiple times. Boolean values (true/false) and numbers are auto-converted. Examples: --feature-flag show_signin_button=true or --feature-flag show_signin_button") parser.add_argument("--list-feature-flags", action="store_true", help="Print the registry of known CLI-settable feature flags as JSON and exit.") diff --git a/comfy_api/feature_flags.py b/comfy_api/feature_flags.py index 682673ab2..4f7365243 100644 --- a/comfy_api/feature_flags.py +++ b/comfy_api/feature_flags.py @@ -162,4 +162,13 @@ def get_server_features() -> dict[str, Any]: Returns: Dictionary of server feature flags """ - return SERVER_FEATURE_FLAGS.copy() + features = SERVER_FEATURE_FLAGS.copy() + # Advertise the assets capability based on live backend availability rather + # than a static default, so clients degrade gracefully when the database + # failed to initialize or its dependencies are missing. + try: + from app.assets.api.routes import assets_enabled + features["assets"] = assets_enabled() + except Exception: + features["assets"] = False + return features diff --git a/main.py b/main.py index a55f84059..0a2aaefc7 100644 --- a/main.py +++ b/main.py @@ -20,6 +20,7 @@ from app.logger import setup_logger setup_logger(log_level=args.verbose, use_stdout=args.log_stdout) from app.assets.seeder import asset_seeder +from app.assets.api.routes import disable_assets_routes from app.assets.services import register_output_files import itertools import utils.extra_config @@ -459,6 +460,12 @@ def setup_database(): init_db() if asset_seeder.start(roots=("models", "input", "output"), prune_first=True, compute_hashes=args.enable_asset_hashing): logging.info("Background asset scan initiated for models, input, output") + else: + # Optional DB dependencies are missing, so init_db() is skipped and the + # asset backend has no database. Disable assets so /api/assets/* returns + # a clean 503 instead of 500s against an uninitialized DB. + disable_assets_routes() + asset_seeder.disable() except Exception as e: if "database is locked" in str(e): logging.error( @@ -467,6 +474,10 @@ def setup_database(): " --database-url sqlite:///path/to/another.db" ) sys.exit(1) + # The database is unusable. Fail safe by disabling assets so endpoints + # return 503 (service unavailable) rather than 500s on every request. + disable_assets_routes() + asset_seeder.disable() logging.error(f"Failed to initialize database. Please ensure you have installed the latest requirements. If the error persists, please report this as in future the database will be required: {e}")