From cc62e89152fea0f858f0b2fdd9b23ecc539f43e3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 17 May 2026 23:49:00 -0500 Subject: [PATCH] fix: guard against empty choices in OpenAI and AstraFlow LLM providers The OpenAI-compatible API can return HTTP 200 with an empty choices list or choices[0].message = None (content-filtered responses on Gemini, overwhelmed Ollama instances). Without a guard, both sites raise an unhandled IndexError or AttributeError crashing the provider. Added guard in OpenAIProvider.generate() and AstraFlowProvider.generate(). --- src/llm/providers/astraflow.py | 2 ++ src/llm/providers/openai.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/llm/providers/astraflow.py b/src/llm/providers/astraflow.py index ba23517f..1a589713 100644 --- a/src/llm/providers/astraflow.py +++ b/src/llm/providers/astraflow.py @@ -79,6 +79,8 @@ class _AstraflowBaseProvider(LLMProvider): params["tools"] = [tool.to_openai_tool() for tool in llm_input.tools] response = self.client.chat.completions.create(**params) + if not response.choices or response.choices[0].message is None: + raise ValueError("LLM returned empty or filtered response") choice = response.choices[0] tool_calls = None diff --git a/src/llm/providers/openai.py b/src/llm/providers/openai.py index e4e7f895..6b6f070c 100644 --- a/src/llm/providers/openai.py +++ b/src/llm/providers/openai.py @@ -67,9 +67,11 @@ class OpenAIProvider(LLMProvider): if input.max_tokens: params["max_tokens"] = input.max_tokens if input.tools: - params["tools"] = [tool.to_openai_tool() for tool in input.tools] + params["tools"] = [tool.to_openai_tool() for tool in input.tools] response = self.client.chat.completions.create(**params) + if not response.choices or response.choices[0].message is None: + raise ValueError("LLM returned empty or filtered response") choice = response.choices[0] tool_calls = None