From e13ffb766c6fcf05ff7080681055c2141d09aa64 Mon Sep 17 00:00:00 2001 From: Paulo Date: Thu, 22 Oct 2026 17:14:48 +0200 Subject: [PATCH] Pass a string 422 detail through to SandboxValidationError --- src/drukbox_sdk/api.py | 10 +++++----- tests/test_api.py | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/drukbox_sdk/api.py b/src/drukbox_sdk/api.py index 52116a6..86be414 100644 --- a/src/drukbox_sdk/api.py +++ b/src/drukbox_sdk/api.py @@ -626,11 +626,11 @@ async def _request( raise SandboxUnavailableError(json_response.get("detail", "service unavailable")) if response.status_code == 422: - # FastAPI's 422 detail is a list of error dicts; join the messages - # so it reads as a line, not a raw list repr. - errors = json_response.get("detail") or [] - detail = "; ".join(error.get("msg", "") for error in errors) or "validation error" - raise SandboxValidationError(detail) + # The detail is FastAPI's list of error dicts or the service's own sentence. + detail = json_response.get("detail") + if isinstance(detail, list): + detail = "; ".join(error.get("msg", "") for error in detail) + raise SandboxValidationError(detail or "validation error") if response.status_code >= 400: raise SandboxResponseError(json_response.get("detail", "error")) diff --git a/tests/test_api.py b/tests/test_api.py index e999ffe..58e2617 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -744,6 +744,20 @@ async def test_422_raises_sandbox_validation_error(api: SandboxAPI): await api.create_host(env={"FOO BAR": "x"}) +@respx.mock +async def test_422_string_detail_raises_sandbox_validation_error(api: SandboxAPI): + # Drukbox answers a refused secret with the issuer's reason as a plain string. + respx.post(f"{BASE_URL}/hosts").mock( + return_value=httpx.Response( + 422, + json={"detail": "GitHub App not installed for acme", "error_code": "SECRET_REFUSED"}, + ), + ) + + with pytest.raises(SandboxValidationError, match=r"^GitHub App not installed for acme$"): + await api.create_host() + + @respx.mock async def test_500_raises_sandbox_response_error(api: SandboxAPI): respx.get(f"{BASE_URL}/hosts").mock(