From cc7710b75957f6636310f59d001d4f82c77c222d Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Tue, 3 Mar 2026 18:14:19 -0800 Subject: [PATCH] fix(guardrail_endpoints): handle string ui_type values in _build_field_dict _build_field_dict unconditionally called .value on ui_type, which crashes for guardrail configs that use plain strings (e.g. BlockCodeExecutionGuardrailConfigModel uses "multiselect" and "percentage"). Now checks with hasattr before calling .value. Co-Authored-By: Claude Opus 4.6 --- .../proxy/guardrails/guardrail_endpoints.py | 3 +- .../guardrails/test_guardrail_endpoints.py | 45 ++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/litellm/proxy/guardrails/guardrail_endpoints.py b/litellm/proxy/guardrails/guardrail_endpoints.py index dd809e4882b..fdefbf904dd 100644 --- a/litellm/proxy/guardrails/guardrail_endpoints.py +++ b/litellm/proxy/guardrails/guardrail_endpoints.py @@ -1173,7 +1173,8 @@ def _build_field_dict( # Check for custom UI type override field_json_schema_extra = getattr(field, "json_schema_extra", {}) if field_json_schema_extra and "ui_type" in field_json_schema_extra: - field_type = field_json_schema_extra["ui_type"].value + ui_type = field_json_schema_extra["ui_type"] + field_type = ui_type.value if hasattr(ui_type, "value") else ui_type elif field_json_schema_extra and "type" in field_json_schema_extra: field_type = field_json_schema_extra["type"] diff --git a/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py b/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py index 0ac3637b380..59bca884db7 100644 --- a/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py +++ b/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py @@ -1103,4 +1103,47 @@ async def test_get_guardrail_info_endpoint_db_guardrail(mocker): assert isinstance(result, GuardrailInfoResponse) assert result.guardrail_id == "test-db-guardrail" assert result.guardrail_name == "Test DB Guardrail" - assert result.guardrail_definition_location == "db" \ No newline at end of file + assert result.guardrail_definition_location == "db" + + +class TestBuildFieldDict: + """Test _build_field_dict handles both enum and string ui_type values.""" + + def test_build_field_dict_with_string_ui_type(self): + """Test that _build_field_dict works when ui_type is a plain string (e.g. BlockCodeExecutionGuardrailConfigModel).""" + from unittest.mock import MagicMock + + from litellm.proxy.guardrails.guardrail_endpoints import _build_field_dict + + field = MagicMock() + field.json_schema_extra = {"ui_type": "multiselect", "options": ["python", "javascript"]} + + result = _build_field_dict( + field=field, + field_annotation=str, + description="Test field", + required=False, + ) + + assert result["type"] == "multiselect" + assert result["description"] == "Test field" + + def test_build_field_dict_with_enum_ui_type(self): + """Test that _build_field_dict works when ui_type is a GuardrailParamUITypes enum.""" + from unittest.mock import MagicMock + + from litellm.proxy.guardrails.guardrail_endpoints import _build_field_dict + from litellm.types.guardrails import GuardrailParamUITypes + + field = MagicMock() + field.json_schema_extra = {"ui_type": GuardrailParamUITypes.BOOL} + + result = _build_field_dict( + field=field, + field_annotation=bool, + description="Test bool field", + required=True, + ) + + assert result["type"] == "bool" + assert result["required"] is True \ No newline at end of file