From d50bf87088677d980a16bcbec44b99bb54857bbd Mon Sep 17 00:00:00 2001 From: James Hush Date: Wed, 22 Oct 2025 15:29:06 +0800 Subject: [PATCH] Add comprehensive error handling to OpenAI LLM service - Import ErrorFrame from pipecat.frames.frames - Add catch-all exception handler matching Anthropic service pattern - Handle asyncio.CancelledError by re-raising to maintain proper cancellation - Catch and log all other exceptions with full traceback - Push ErrorFrame upstream on exceptions for error detection - Maintain existing httpx.TimeoutException handling - Ensure LLMFullResponseEndFrame always sent in finally block This change enables consistent error propagation across all LLM services, allowing downstream error monitors to detect failures and implement fallback strategies like LLM hot-switching. Fixes issue where OpenAI service errors were suppressed and not communicated through the frame pipeline, making automatic error recovery impossible. --- src/pipecat/services/openai/base_llm.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pipecat/services/openai/base_llm.py b/src/pipecat/services/openai/base_llm.py index d020e1106..5953e242c 100644 --- a/src/pipecat/services/openai/base_llm.py +++ b/src/pipecat/services/openai/base_llm.py @@ -13,18 +13,13 @@ from typing import Any, Dict, List, Mapping, Optional import httpx from loguru import logger -from openai import ( - NOT_GIVEN, - APITimeoutError, - AsyncOpenAI, - AsyncStream, - DefaultAsyncHttpxClient, -) +from openai import NOT_GIVEN, APITimeoutError, AsyncOpenAI, AsyncStream, DefaultAsyncHttpxClient from openai.types.chat import ChatCompletionChunk, ChatCompletionMessageParam from pydantic import BaseModel, Field from pipecat.adapters.services.open_ai_adapter import OpenAILLMInvocationParams from pipecat.frames.frames import ( + ErrorFrame, Frame, LLMContextFrame, LLMFullResponseEndFrame, @@ -460,8 +455,13 @@ class BaseOpenAILLMService(LLMService): await self.push_frame(LLMFullResponseStartFrame()) await self.start_processing_metrics() await self._process_context(context) + except asyncio.CancelledError: + raise except httpx.TimeoutException: await self._call_event_handler("on_completion_timeout") + except Exception as e: + logger.exception(f"{self} exception: {e}") + await self.push_error(ErrorFrame(f"{e}")) finally: await self.stop_processing_metrics() await self.push_frame(LLMFullResponseEndFrame())