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
10 changes: 10 additions & 0 deletions posthog/ai/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,16 @@ def _fetch_prompt_from_api(
if response.status_code == 404:
raise Exception(f"[PostHog Prompts] {prompt_title} not found")

if response.status_code == 401:
raise Exception(
f"[PostHog Prompts] Authentication failed for {prompt_reference}. "
"The key may be missing, expired, or the wrong type. Prompt fetches "
"require a personal API key (starts with 'phx_'); a project secret "
"key is not accepted. Pass this key as personal_api_key when you "
"construct Prompts directly, or as secret_key when you configure the "
"PostHog client."
)

if response.status_code == 403:
raise Exception(
f"[PostHog Prompts] Access denied for {prompt_reference}. "
Expand Down
16 changes: 16 additions & 0 deletions posthog/test/ai/test_prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,22 @@ def test_handle_403_response(self, mock_get_session):
'Access denied for prompt "restricted-prompt"', str(context.exception)
)

@patch("posthog.ai.prompts._get_session")
def test_handle_401_response(self, mock_get_session):
"""Should explain the likely auth causes on a 401 response."""
mock_get = mock_get_session.return_value.get
mock_get.return_value = MockResponse(status_code=401, ok=False)

posthog = self.create_mock_posthog()
prompts = Prompts(posthog)

with self.assertRaises(Exception) as context:
prompts.get("restricted-prompt", with_metadata=False)

message = str(context.exception)
self.assertIn('Authentication failed for prompt "restricted-prompt"', message)
self.assertIn("personal API key", message)

def test_throw_when_no_personal_api_key_configured(self):
"""Should throw when no personal_api_key is configured."""
posthog = self.create_mock_posthog(personal_api_key=None)
Expand Down