diff --git a/litellm-proxy-extras/litellm_proxy_extras/utils.py b/litellm-proxy-extras/litellm_proxy_extras/utils.py index 7eff0c00f75..cdc8c95972a 100644 --- a/litellm-proxy-extras/litellm_proxy_extras/utils.py +++ b/litellm-proxy-extras/litellm_proxy_extras/utils.py @@ -234,7 +234,6 @@ class ProxyExtrasDBManager: r"duplicate key value violates", r"relation .* already exists", r"constraint .* already exists", - r"does not exist", r"Can't drop database.* because it doesn't exist", ] @@ -326,9 +325,20 @@ class ProxyExtrasDBManager: logger.info(f"prisma db execute stdout: {result.stdout}") logger.info("✅ Migration diff applied successfully") except subprocess.CalledProcessError as e: - logger.warning(f"Failed to apply migration diff: {e.stderr}") + logger.error( + f"Failed to apply migration diff: {e.stderr}. " + f"Will NOT mark migrations as applied." + ) + raise RuntimeError( + f"Migration diff application failed. Migrations will not be marked as applied. " + f"Please check the database state and apply the diff manually. Error: {e.stderr}" + ) from e except subprocess.TimeoutExpired: - logger.warning("Migration diff application timed out.") + logger.error("Migration diff application timed out. Will NOT mark migrations as applied.") + raise RuntimeError( + "Migration diff application timed out. Migrations will not be marked as applied. " + "Please check the database state and apply the diff manually." + ) # 3. Mark all migrations as applied if not mark_all_applied: diff --git a/tests/litellm-proxy-extras/test_litellm_proxy_extras_utils.py b/tests/litellm-proxy-extras/test_litellm_proxy_extras_utils.py index c1e3fd5072f..1d610633664 100644 --- a/tests/litellm-proxy-extras/test_litellm_proxy_extras_utils.py +++ b/tests/litellm-proxy-extras/test_litellm_proxy_extras_utils.py @@ -109,9 +109,19 @@ class TestIdempotentErrorDetection: error_message = "constraint 'fk_user_id' already exists" assert ProxyExtrasDBManager._is_idempotent_error(error_message) is True - def test_is_idempotent_error_does_not_exist(self): - """Test detection of 'does not exist' error""" + def test_is_idempotent_error_does_not_exist_is_not_idempotent(self): + """Generic 'does not exist' errors are NOT idempotent — they indicate real failures""" error_message = "ERROR: index 'idx' does not exist" + assert ProxyExtrasDBManager._is_idempotent_error(error_message) is False + + def test_is_idempotent_error_relation_does_not_exist_is_not_idempotent(self): + """Relation 'does not exist' errors are NOT idempotent""" + error_message = 'ERROR: relation "LiteLLM_DailyAgentSpend" does not exist' + assert ProxyExtrasDBManager._is_idempotent_error(error_message) is False + + def test_is_idempotent_error_cant_drop_database_is_idempotent(self): + """Can't drop database because it doesn't exist IS idempotent""" + error_message = "Can't drop database 'litellm' because it doesn't exist" assert ProxyExtrasDBManager._is_idempotent_error(error_message) is True def test_is_idempotent_error_case_insensitive(self): @@ -119,11 +129,6 @@ class TestIdempotentErrorDetection: error_message = "COLUMN 'ID' ALREADY EXISTS" assert ProxyExtrasDBManager._is_idempotent_error(error_message) is True - def test_is_idempotent_error_does_not_exist(self): - """Test detection of 'does not exist' error""" - error_message = "ERROR: index 'idx' does not exist" - assert ProxyExtrasDBManager._is_idempotent_error(error_message) is True - def test_is_idempotent_error_negative(self): """Test that non-idempotent errors are not detected as idempotent errors""" error_message = "Database error code: 42501 - permission denied"