Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion workflowai/core/client/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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),
Expand Down
15 changes: 14 additions & 1 deletion workflowai/core/client/_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
3 changes: 2 additions & 1 deletion workflowai/core/domain/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."
)
Expand Down