From b0f8e16ac0446be5cb310eadd742ff89e97fc183 Mon Sep 17 00:00:00 2001 From: Kian Jones <11655409+kianjones9@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:03:43 -0800 Subject: [PATCH] fix: check both unique constraints in provider model sync (#9193) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sync_provider_models_async function was only checking for existing models by (handle, organization_id, model_type) before creating, but the database has a second unique constraint on (name, provider_id, model_type). This caused UniqueConstraintViolationError when a model with the same name/provider already existed under a different handle. 🤖 Generated with [Letta Code](https://letta.com) Co-authored-by: Letta --- letta/services/provider_manager.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/letta/services/provider_manager.py b/letta/services/provider_manager.py index 1556ecef..52b46495 100644 --- a/letta/services/provider_manager.py +++ b/letta/services/provider_manager.py @@ -675,7 +675,7 @@ class ProviderManager: for llm_config in llm_models: logger.info(f" Checking LLM model: {llm_config.handle} (name: {llm_config.model})") - # Check if model already exists (excluding soft-deleted ones) + # Check if model already exists by handle (excluding soft-deleted ones) existing = await ProviderModelORM.list_async( db_session=session, limit=1, @@ -687,6 +687,19 @@ class ProviderManager: }, ) + # Also check by name+provider_id (covers unique_model_per_provider_and_type constraint) + if not existing: + existing = await ProviderModelORM.list_async( + db_session=session, + limit=1, + check_is_deleted=True, + **{ + "name": llm_config.model, + "provider_id": provider.id, + "model_type": "llm", + }, + ) + if not existing: logger.info(f" Creating new LLM model {llm_config.handle}") # Create new model entry @@ -754,7 +767,7 @@ class ProviderManager: for embedding_config in embedding_models: logger.info(f" Checking embedding model: {embedding_config.handle} (name: {embedding_config.embedding_model})") - # Check if model already exists (excluding soft-deleted ones) + # Check if model already exists by handle (excluding soft-deleted ones) existing = await ProviderModelORM.list_async( db_session=session, limit=1, @@ -766,6 +779,19 @@ class ProviderManager: }, ) + # Also check by name+provider_id (covers unique_model_per_provider_and_type constraint) + if not existing: + existing = await ProviderModelORM.list_async( + db_session=session, + limit=1, + check_is_deleted=True, + **{ + "name": embedding_config.embedding_model, + "provider_id": provider.id, + "model_type": "embedding", + }, + ) + if not existing: logger.info(f" Creating new embedding model {embedding_config.handle}") # Create new model entry