Skip to content

Commit 69af099

Browse files
committed
Warn on invalid model configs in the DB rather than crashing.
1 parent 5795617 commit 69af099

File tree

5 files changed

+24
-7
lines changed

5 files changed

+24
-7
lines changed

docs/contributing/MODEL_MANAGER.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ config = get_config()
408408
409409
logger = InvokeAILogger.get_logger(config=config)
410410
db = SqliteDatabase(config.db_path, logger)
411-
record_store = ModelRecordServiceSQL(db)
411+
record_store = ModelRecordServiceSQL(db, logger)
412412
queue = DownloadQueueService()
413413
queue.start()
414414

invokeai/app/api/dependencies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def initialize(config: InvokeAIAppConfig, event_handler_id: int, logger: Logger
9999
model_images_service = ModelImageFileStorageDisk(model_images_folder / "model_images")
100100
model_manager = ModelManagerService.build_model_manager(
101101
app_config=configuration,
102-
model_record_service=ModelRecordServiceSQL(db=db),
102+
model_record_service=ModelRecordServiceSQL(db=db, logger=logger),
103103
download_queue=download_queue_service,
104104
events=events,
105105
)

invokeai/app/services/model_records/model_records_sql.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@
4040
"""
4141

4242
import json
43+
import logging
4344
import sqlite3
4445
from math import ceil
4546
from pathlib import Path
4647
from typing import List, Optional, Union
4748

49+
import pydantic
50+
4851
from invokeai.app.services.model_records.model_records_base import (
4952
DuplicateModelException,
5053
ModelRecordChanges,
@@ -67,7 +70,7 @@
6770
class ModelRecordServiceSQL(ModelRecordServiceBase):
6871
"""Implementation of the ModelConfigStore ABC using a SQL database."""
6972

70-
def __init__(self, db: SqliteDatabase):
73+
def __init__(self, db: SqliteDatabase, logger: logging.Logger):
7174
"""
7275
Initialize a new object from preexisting sqlite3 connection and threading lock objects.
7376
@@ -76,6 +79,7 @@ def __init__(self, db: SqliteDatabase):
7679
super().__init__()
7780
self._db = db
7881
self._cursor = db.conn.cursor()
82+
self._logger = logger
7983

8084
@property
8185
def db(self) -> SqliteDatabase:
@@ -291,7 +295,20 @@ def search_by_attr(
291295
tuple(bindings),
292296
)
293297
result = self._cursor.fetchall()
294-
results = [ModelConfigFactory.make_config(json.loads(x[0]), timestamp=x[1]) for x in result]
298+
299+
# Parse the model configs.
300+
results: list[AnyModelConfig] = []
301+
for row in result:
302+
try:
303+
model_config = ModelConfigFactory.make_config(json.loads(row[0]), timestamp=row[1])
304+
except pydantic.ValidationError:
305+
# We catch this error so that the app can still run if there are invalid model configs in the database.
306+
# One reason that an invalid model config might be in the database is if someone had to rollback from a
307+
# newer version of the app that added a new model type.
308+
self._logger.warning(f"Found an invalid model config in the database. Ignoring this model. ({row[0]})")
309+
else:
310+
results.append(model_config)
311+
295312
return results
296313

297314
def search_by_path(self, path: Union[str, Path]) -> List[AnyModelConfig]:

tests/app/services/model_records/test_model_records_sql.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def store(
4040
config._root = datadir
4141
logger = InvokeAILogger.get_logger(config=config)
4242
db = create_mock_sqlite_database(config, logger)
43-
return ModelRecordServiceSQL(db)
43+
return ModelRecordServiceSQL(db, logger)
4444

4545

4646
def example_ti_config(key: Optional[str] = None) -> TextualInversionFileConfig:

tests/backend/model_manager/model_manager_fixtures.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def mm2_installer(
110110
logger = InvokeAILogger.get_logger()
111111
db = create_mock_sqlite_database(mm2_app_config, logger)
112112
events = TestEventService()
113-
store = ModelRecordServiceSQL(db)
113+
store = ModelRecordServiceSQL(db, logger)
114114

115115
installer = ModelInstallService(
116116
app_config=mm2_app_config,
@@ -128,7 +128,7 @@ def mm2_installer(
128128
def mm2_record_store(mm2_app_config: InvokeAIAppConfig) -> ModelRecordServiceBase:
129129
logger = InvokeAILogger.get_logger(config=mm2_app_config)
130130
db = create_mock_sqlite_database(mm2_app_config, logger)
131-
store = ModelRecordServiceSQL(db)
131+
store = ModelRecordServiceSQL(db, logger)
132132
# add five simple config records to the database
133133
config1 = VAEDiffusersConfig(
134134
key="test_config_1",

0 commit comments

Comments
 (0)