fix: skip frozen fields when applying settings payload

The secrets_store field on Settings is frozen, so setattr() raised a
validation error when the POST /api/settings payload included that key.

Filter out any frozen field before calling setattr in
_apply_settings_payload. Added a regression test.

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
openhands
2026-03-18 14:04:46 +00:00
parent 3ed37e18ac
commit 017d758a76
2 changed files with 21 additions and 1 deletions

View File

@@ -104,6 +104,11 @@ def _extract_sdk_settings_values(
return values
_SETTINGS_FROZEN_FIELDS = frozenset(
name for name, field_info in Settings.model_fields.items() if field_info.frozen
)
def _apply_settings_payload(
payload: dict[str, Any],
existing_settings: Settings | None,
@@ -116,7 +121,7 @@ def _apply_settings_payload(
sdk_settings_values = dict(settings.sdk_settings_values)
for key, value in payload.items():
if key in Settings.model_fields:
if key in Settings.model_fields and key not in _SETTINGS_FROZEN_FIELDS:
setattr(settings, key, value)
if key in sdk_field_keys and key not in secret_field_keys:

View File

@@ -270,6 +270,21 @@ async def test_settings_api_endpoints(test_client):
assert response.status_code == 200
@pytest.mark.asyncio
async def test_saving_settings_with_frozen_secrets_store(test_client):
"""Regression: POSTing settings must not fail when the payload includes
``secrets_store`` (a frozen field on the Settings model).
See https://github.com/OpenHands/OpenHands/issues/13306.
"""
settings_data = {
'language': 'en',
'llm_model': 'gpt-4',
'secrets_store': {'provider_tokens': {}},
}
response = test_client.post('/api/settings', json=settings_data)
assert response.status_code == 200
@pytest.mark.asyncio
async def test_search_api_key_preservation(test_client):
"""Test that search_api_key is preserved when sending an empty string."""