From e3354929a33fe2963bbe4e6e1b2d9760ca8a8be3 Mon Sep 17 00:00:00 2001 From: Husain Baghwala Date: Sat, 1 Nov 2025 20:01:28 +0530 Subject: [PATCH 1/4] feat: improve error handling for Anthropic API responses - Added transform_error_response function to standardize error handling across services - Implemented specialized handling for Anthropic API's response_type parameter errors - Updated chat and image endpoints to use new error transformation logic - Added debug logging to track error transformation process - Fixed potential KeyError by using .get() for is_playground checks in error handlers --- src/services/commonServices/common.py | 22 ++++---- src/services/utils/common_utils.py | 72 +++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/src/services/commonServices/common.py b/src/services/commonServices/common.py index b9662efa..af700b4f 100644 --- a/src/services/commonServices/common.py +++ b/src/services/commonServices/common.py @@ -2,6 +2,8 @@ from fastapi import FastAPI from fastapi.responses import JSONResponse import traceback +from exceptions.bad_request import BadRequestException +from src.services.utils.logger import logger from ...db_services import metrics_service as metrics_service import pydash as _ from ..utils.helper import Helper @@ -34,15 +36,12 @@ create_history_params, add_files_to_parse_data, orchestrator_agent_chat, - process_background_tasks_for_playground + process_background_tasks_for_playground, + transform_error_response ) from src.services.utils.guardrails_validator import guardrails_check from src.services.utils.rich_text_support import process_chatbot_response app = FastAPI() -from src.services.utils.helper import Helper -from src.services.commonServices.testcases import run_testcases as run_bridge_testcases -from globals import * -from src.services.cache_service import find_in_cache configurationModel = db["configurations"] @@ -233,7 +232,7 @@ async def chat(request_body): except (Exception, ValueError, BadRequestException) as error: if not isinstance(error, BadRequestException): logger.error(f'Error in chat service: %s, {str(error)}, {traceback.format_exc()}') - if not parsed_data['is_playground']: + if not parsed_data.get('is_playground', True): # Create latency object and update usage metrics latency = create_latency_object(timer, params) update_usage_metrics(parsed_data, params, latency, error=error, success=False) @@ -243,8 +242,9 @@ async def chat(request_body): await sendResponse(parsed_data['response_format'], result.get("error", str(error)), variables=parsed_data['variables']) if parsed_data['response_format']['type'] != 'default' else None # Process background tasks for error handling await process_background_tasks_for_error(parsed_data, error) - # Add support contact information to error message - error_message = f"{str(error)}. For more support contact us at support@gtwy.ai" + # Transform error using one-line function and add support contact information + transformed_error = transform_error_response(error, parsed_data) + error_message = f"{transformed_error}. For more support contact us at support@gtwy.ai" raise ValueError(error_message) @@ -422,7 +422,7 @@ async def image(request_body): except (Exception, ValueError, BadRequestException) as error: if not isinstance(error, BadRequestException): logger.error(f'Error in image service: {str(error)}, {traceback.format_exc()}') - if not parsed_data['is_playground']: + if not parsed_data.get('is_playground', True): # Create latency object and update usage metrics latency = create_latency_object(timer, params) update_usage_metrics(parsed_data, params, latency, error=error, success=False) @@ -432,4 +432,6 @@ async def image(request_body): await sendResponse(parsed_data['response_format'], result.get("modelResponse", str(error)), variables=parsed_data['variables']) if parsed_data['response_format']['type'] != 'default' else None # Process background tasks for error handling await process_background_tasks_for_error(parsed_data, error) - raise ValueError(error) + # Transform error using one-line function + transformed_error = transform_error_response(error, parsed_data) + raise ValueError(transformed_error) diff --git a/src/services/utils/common_utils.py b/src/services/utils/common_utils.py index 4f6092df..839186ac 100644 --- a/src/services/utils/common_utils.py +++ b/src/services/utils/common_utils.py @@ -29,6 +29,78 @@ from src.services.utils.rich_text_support import process_chatbot_response from src.db_services.orchestrator_history_service import OrchestratorHistoryService, orchestrator_collector +def handle_anthropic_response_type_error(error_str, parsed_data=None): + """ + Handle specific Anthropic API error for unexpected 'response_type' keyword argument. + Returns a proper JSON schema instead of empty objects. + """ + # Check if this is the specific Anthropic response_type error + if ("anthropic api AsyncMessages.stream() got an unexpected keyword argument 'response_type'" in str(error_str) or + "unexpected keyword argument 'response_type'" in str(error_str)): + + # Create proper JSON schema response + proper_response = { + 'success': False, + 'error': 'Anthropic API does not support response_type parameter. Please remove response_type from your configuration or use a different model provider.', + 'response': { + 'usage': { + 'prompt_tokens': 0, + 'completion_tokens': 0, + 'total_tokens': 0, + 'cost': 0 + }, + 'data': { + 'message': 'Error: Anthropic models do not support structured output via response_type parameter.', + 'suggestion': 'Consider using OpenAI models for structured JSON responses or modify your prompt to request JSON format naturally.', + 'error_type': 'unsupported_parameter' + } + }, + 'modelResponse': { + 'error': 'response_type_not_supported', + 'provider': 'anthropic', + 'supported_features': ['text_generation', 'conversation', 'tool_calling'], + 'unsupported_features': ['structured_output_response_type'] + } + } + + # Add bridge_id and org_id if available from parsed_data + if parsed_data: + proper_response['response']['data']['bridge_id'] = parsed_data.get('bridge_id') + proper_response['response']['data']['org_id'] = parsed_data.get('org_id') + proper_response['response']['data']['model'] = parsed_data.get('model') + proper_response['response']['data']['service'] = parsed_data.get('service') + + return proper_response + + return None + +def transform_error_response(error, parsed_data=None): + """ + Simple one-line function to transform error into proper structured response. + Returns the new error if it matches specific patterns, otherwise returns original error. + """ + # Handle both string errors and dictionary errors + error_str = str(error) + + # Debug: Print the error to see what we're getting + print(f"DEBUG: Error type: {type(error)}") + print(f"DEBUG: Error string: {error_str}") + + # Check for the specific Anthropic response_type error in any format + if ("AsyncMessages.stream() got an unexpected keyword argument" in error_str and + "response_type" in error_str): + print("DEBUG: Anthropic error detected, transforming...") + return 'Anthropic API does not support response_type parameter. Please remove response_type from your configuration or use a different model provider.' + + # Check for the direct error pattern using the original function + transformed_error = handle_anthropic_response_type_error(error_str, parsed_data) + if transformed_error: + print("DEBUG: Transformed using handle_anthropic_response_type_error") + return transformed_error['error'] + + print("DEBUG: No transformation applied, returning original error") + return str(error) + def parse_request_body(request_body): body = request_body.get('body', {}) state = request_body.get('state', {}) From 9d88b99583e2b78c990be1ea5afbe3c143933abb Mon Sep 17 00:00:00 2001 From: Husain Baghwala Date: Sat, 1 Nov 2025 20:02:14 +0530 Subject: [PATCH 2/4] refactor: remove debug print statements from error handling - Removed unnecessary debug print statements from transform_error_response function - Simplified error transformation logic while maintaining core functionality - Kept existing error handling behavior for Anthropic API and response_type errors --- src/services/utils/common_utils.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/services/utils/common_utils.py b/src/services/utils/common_utils.py index 839186ac..32fb7ee2 100644 --- a/src/services/utils/common_utils.py +++ b/src/services/utils/common_utils.py @@ -82,23 +82,16 @@ def transform_error_response(error, parsed_data=None): # Handle both string errors and dictionary errors error_str = str(error) - # Debug: Print the error to see what we're getting - print(f"DEBUG: Error type: {type(error)}") - print(f"DEBUG: Error string: {error_str}") - # Check for the specific Anthropic response_type error in any format if ("AsyncMessages.stream() got an unexpected keyword argument" in error_str and "response_type" in error_str): - print("DEBUG: Anthropic error detected, transforming...") return 'Anthropic API does not support response_type parameter. Please remove response_type from your configuration or use a different model provider.' # Check for the direct error pattern using the original function transformed_error = handle_anthropic_response_type_error(error_str, parsed_data) if transformed_error: - print("DEBUG: Transformed using handle_anthropic_response_type_error") return transformed_error['error'] - print("DEBUG: No transformation applied, returning original error") return str(error) def parse_request_body(request_body): From b2d32f326defd0433778f7a99d1253f9e87d7f0d Mon Sep 17 00:00:00 2001 From: Husain Baghwala Date: Sat, 1 Nov 2025 20:07:07 +0530 Subject: [PATCH 3/4] refactor: simplify Anthropic error handling logic - Reduced handle_anthropic_response_type_error function to return simple error message instead of complex JSON schema - Removed unused fields and nested response structure for better maintainability - Updated error message format in transform_error_response for consistency - Removed redundant parsed_data parameter handling since it's no longer needed --- src/services/utils/common_utils.py | 38 ++++-------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/src/services/utils/common_utils.py b/src/services/utils/common_utils.py index 32fb7ee2..90599155 100644 --- a/src/services/utils/common_utils.py +++ b/src/services/utils/common_utils.py @@ -32,45 +32,15 @@ def handle_anthropic_response_type_error(error_str, parsed_data=None): """ Handle specific Anthropic API error for unexpected 'response_type' keyword argument. - Returns a proper JSON schema instead of empty objects. + Returns error message if pattern matches, otherwise None. """ # Check if this is the specific Anthropic response_type error if ("anthropic api AsyncMessages.stream() got an unexpected keyword argument 'response_type'" in str(error_str) or "unexpected keyword argument 'response_type'" in str(error_str)): - # Create proper JSON schema response - proper_response = { - 'success': False, - 'error': 'Anthropic API does not support response_type parameter. Please remove response_type from your configuration or use a different model provider.', - 'response': { - 'usage': { - 'prompt_tokens': 0, - 'completion_tokens': 0, - 'total_tokens': 0, - 'cost': 0 - }, - 'data': { - 'message': 'Error: Anthropic models do not support structured output via response_type parameter.', - 'suggestion': 'Consider using OpenAI models for structured JSON responses or modify your prompt to request JSON format naturally.', - 'error_type': 'unsupported_parameter' - } - }, - 'modelResponse': { - 'error': 'response_type_not_supported', - 'provider': 'anthropic', - 'supported_features': ['text_generation', 'conversation', 'tool_calling'], - 'unsupported_features': ['structured_output_response_type'] - } + return { + 'error': 'Anthropic API does not support response_type parameter. Please remove response_type from your configuration or use a different model provider.' } - - # Add bridge_id and org_id if available from parsed_data - if parsed_data: - proper_response['response']['data']['bridge_id'] = parsed_data.get('bridge_id') - proper_response['response']['data']['org_id'] = parsed_data.get('org_id') - proper_response['response']['data']['model'] = parsed_data.get('model') - proper_response['response']['data']['service'] = parsed_data.get('service') - - return proper_response return None @@ -85,7 +55,7 @@ def transform_error_response(error, parsed_data=None): # Check for the specific Anthropic response_type error in any format if ("AsyncMessages.stream() got an unexpected keyword argument" in error_str and "response_type" in error_str): - return 'Anthropic API does not support response_type parameter. Please remove response_type from your configuration or use a different model provider.' + return 'Anthropic API does not support {} as JSON SCHEMA. Please update response_type.' # Check for the direct error pattern using the original function transformed_error = handle_anthropic_response_type_error(error_str, parsed_data) From e14f9b982076e6261ed935a17e0fa6c8703c84b2 Mon Sep 17 00:00:00 2001 From: Husain Baghwala Date: Mon, 3 Nov 2025 15:59:08 +0530 Subject: [PATCH 4/4] refactor: simplify error handling for Anthropic API responses - Consolidated error transformation logic into single transform_error_response function - Removed redundant handle_anthropic_response_type_error helper function - Moved support contact info into error transformation function for consistent messaging - Simplified error handling flow in chat function by removing parsed_data parameter --- src/services/commonServices/common.py | 7 +++---- src/services/utils/common_utils.py | 26 +++----------------------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/services/commonServices/common.py b/src/services/commonServices/common.py index af700b4f..aa52bacc 100644 --- a/src/services/commonServices/common.py +++ b/src/services/commonServices/common.py @@ -242,10 +242,9 @@ async def chat(request_body): await sendResponse(parsed_data['response_format'], result.get("error", str(error)), variables=parsed_data['variables']) if parsed_data['response_format']['type'] != 'default' else None # Process background tasks for error handling await process_background_tasks_for_error(parsed_data, error) - # Transform error using one-line function and add support contact information - transformed_error = transform_error_response(error, parsed_data) - error_message = f"{transformed_error}. For more support contact us at support@gtwy.ai" - raise ValueError(error_message) + # Transform error using one-line function + transformed_error = transform_error_response(error) + raise ValueError(transformed_error) diff --git a/src/services/utils/common_utils.py b/src/services/utils/common_utils.py index 90599155..c4e87c38 100644 --- a/src/services/utils/common_utils.py +++ b/src/services/utils/common_utils.py @@ -29,22 +29,7 @@ from src.services.utils.rich_text_support import process_chatbot_response from src.db_services.orchestrator_history_service import OrchestratorHistoryService, orchestrator_collector -def handle_anthropic_response_type_error(error_str, parsed_data=None): - """ - Handle specific Anthropic API error for unexpected 'response_type' keyword argument. - Returns error message if pattern matches, otherwise None. - """ - # Check if this is the specific Anthropic response_type error - if ("anthropic api AsyncMessages.stream() got an unexpected keyword argument 'response_type'" in str(error_str) or - "unexpected keyword argument 'response_type'" in str(error_str)): - - return { - 'error': 'Anthropic API does not support response_type parameter. Please remove response_type from your configuration or use a different model provider.' - } - - return None - -def transform_error_response(error, parsed_data=None): +def transform_error_response(error): """ Simple one-line function to transform error into proper structured response. Returns the new error if it matches specific patterns, otherwise returns original error. @@ -55,14 +40,9 @@ def transform_error_response(error, parsed_data=None): # Check for the specific Anthropic response_type error in any format if ("AsyncMessages.stream() got an unexpected keyword argument" in error_str and "response_type" in error_str): - return 'Anthropic API does not support {} as JSON SCHEMA. Please update response_type.' - - # Check for the direct error pattern using the original function - transformed_error = handle_anthropic_response_type_error(error_str, parsed_data) - if transformed_error: - return transformed_error['error'] + return 'Anthropic API does not support {} as JSON SCHEMA. Please update response_type. For more support contact us at support@gtwy.ai' - return str(error) + return f"{str(error)}. For more support contact us at support@gtwy.ai" def parse_request_body(request_body): body = request_body.get('body', {})