From 4ee6112161e63c320320da4ad4d56380604c35f1 Mon Sep 17 00:00:00 2001 From: Li-Kuang Chen <38750225+LKChenLK@users.noreply.github.com> Date: Sun, 22 Jun 2025 02:15:21 +0800 Subject: [PATCH] openai[patch]: Improve error message when response type is malformed (#31619) --- .../langchain_openai/chat_models/base.py | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/libs/partners/openai/langchain_openai/chat_models/base.py b/libs/partners/openai/langchain_openai/chat_models/base.py index f9fa43ec9f6..edc5dc56618 100644 --- a/libs/partners/openai/langchain_openai/chat_models/base.py +++ b/libs/partners/openai/langchain_openai/chat_models/base.py @@ -1111,15 +1111,27 @@ class BaseChatOpenAI(BaseChatModel): response_dict = ( response if isinstance(response, dict) else response.model_dump() ) - # Sometimes the AI Model calling will get error, we should raise it. - # Otherwise, the next code 'choices.extend(response["choices"])' - # will throw a "TypeError: 'NoneType' object is not iterable" error - # to mask the true error. Because 'response["choices"]' is None. + # Sometimes the AI Model calling will get error, we should raise it (this is + # typically followed by a null value for `choices`, which we raise for + # separately below). if response_dict.get("error"): raise ValueError(response_dict.get("error")) + # Raise informative error messages for non-OpenAI chat completions APIs + # that return malformed responses. + try: + choices = response_dict["choices"] + except KeyError as e: + raise KeyError( + f"Response missing `choices` key: {response_dict.keys()}" + ) from e + + if choices is None: + raise TypeError("Received response with null value for `choices`.") + token_usage = response_dict.get("usage") - for res in response_dict["choices"]: + + for res in choices: message = _convert_dict_to_message(res["message"]) if token_usage and isinstance(message, AIMessage): message.usage_metadata = _create_usage_metadata(token_usage)