diff --git a/src/api/settings/endpoints.py b/src/api/settings/endpoints.py index b672161c2..7defe344a 100644 --- a/src/api/settings/endpoints.py +++ b/src/api/settings/endpoints.py @@ -1601,12 +1601,12 @@ async def update_docling_preset( settings=settings_toggles, preset_config=preset_config, ) - + except HTTPException: + # Preserve intended HTTP status codes (e.g. 400 for an invalid preset) + raise except Exception as e: logger.error("Failed to update docling settings", error=str(e)) - raise HTTPException( - status_code=500, detail=f"Failed to update docling settings: {str(e)}" - ) from e + raise HTTPException(status_code=500, detail="Failed to update docling settings") from e async def refresh_openrag_docs( diff --git a/tests/unit/api/test_settings_endpoints.py b/tests/unit/api/test_settings_endpoints.py new file mode 100644 index 000000000..88177acb5 --- /dev/null +++ b/tests/unit/api/test_settings_endpoints.py @@ -0,0 +1,37 @@ +""" +Unit tests for api.settings.endpoints +Validates error handling in update_docling_preset endpoint. +""" + +from unittest.mock import AsyncMock, MagicMock + +import pytest +from fastapi import HTTPException + +from api.settings import DoclingPresetBody, update_docling_preset +from session_manager import User + + +@pytest.mark.asyncio +async def test_update_docling_preset_invalid_preset_returns_400(): + """Test that an invalid preset value returns 400 status code. + + This test ensures that the HTTPException with status_code=400 raised + for invalid presets is not masked by the broad Exception handler. + Regression test for issue #1586. + """ + # Create a body with an invalid preset + body = DoclingPresetBody(preset="nonexistent_preset") + + # Mock dependencies + session_manager = AsyncMock() + user = MagicMock(spec=User) + + # Call the endpoint and expect HTTPException with 400 + with pytest.raises(HTTPException) as exc_info: + await update_docling_preset(body=body, session_manager=session_manager, user=user) + + # Assert it's a 400 error (not 500) + assert exc_info.value.status_code == 400 + assert "Invalid preset" in exc_info.value.detail + assert "nonexistent_preset" in exc_info.value.detail