diff --git a/workflowai/core/client/_api.py b/workflowai/core/client/_api.py index 1c793cd..30bea93 100644 --- a/workflowai/core/client/_api.py +++ b/workflowai/core/client/_api.py @@ -6,7 +6,7 @@ from pydantic import BaseModel, TypeAdapter, ValidationError from workflowai.core._logger import logger -from workflowai.core.domain.errors import BaseError, WorkflowAIError +from workflowai.core.domain.errors import BaseError, InvalidAPIKeyError, WorkflowAIError # A type for return values _R = TypeVar("_R") @@ -26,6 +26,11 @@ def _get_url(self, run: bool = False): @asynccontextmanager async def _client(self, run: bool = False): + if not self.api_key: + raise InvalidAPIKeyError( + response=None, + error=BaseError(message="No API key provided", code="invalid_api_key"), + ) source_headers = self.source_headers or {} async with httpx.AsyncClient( base_url=self._get_url(run), diff --git a/workflowai/core/client/_api_test.py b/workflowai/core/client/_api_test.py index ded633e..e634fc0 100644 --- a/workflowai/core/client/_api_test.py +++ b/workflowai/core/client/_api_test.py @@ -6,7 +6,7 @@ from pytest_httpx import HTTPXMock, IteratorStream from workflowai.core.client._api import APIClient -from workflowai.core.domain.errors import WorkflowAIError +from workflowai.core.domain.errors import InvalidAPIKeyError, WorkflowAIError @pytest.fixture @@ -136,3 +136,16 @@ async def test_stream(self, httpx_mock: HTTPXMock, client: APIClient, exception: pass assert e.value.error.code == "connection_error" + + async def test_empty_api_key(self, client: APIClient): + """Check that we return a pretty error when there is no api key provided""" + client.api_key = "" + + # no need to add any response, httpx will complain that the header is illegal + with pytest.raises(InvalidAPIKeyError) as e: + await client.get( + path="test_path", + returns=_TestOutputModel, + ) + assert e.value.error.code == "invalid_api_key" + assert e.value.message.startswith("❌ No API key provided") diff --git a/workflowai/core/domain/errors.py b/workflowai/core/domain/errors.py index bbf37e7..7437bb7 100644 --- a/workflowai/core/domain/errors.py +++ b/workflowai/core/domain/errors.py @@ -188,8 +188,9 @@ class InvalidAPIKeyError(WorkflowAIError): @property @override def message(self) -> str: + base_message = (self.status_code is None and "No API key provided") or "Your API key is invalid" return ( - "❌ Your API key is invalid. Please double-check your API key, " + f"❌ {base_message}. Please double-check your API key, " "or create a new one at https://workflowai.com/organization/settings/api-keys " "or from your self-hosted WorkflowAI instance." )