fix: Chat failed notifications are not sent when the provider returns an error status (#32198)

Notification targets subscribed to Chat failed stayed silent when the provider answered a chat with an error status, such as a 500, or could not be reached at all. Those failures show up as an error in the chat, but only a few uncommon failures were announced to the targets. Now these failures notify Chat failed targets too, with the error text and a link to the chat.

Fixes #32003
This commit is contained in:
Classic298 2026-10-10 18:16:10 +02:00 • committed by GitHub
parent 69a1c57328
commit 0a50954090
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 19 deletions

View file

@ -253,6 +253,7 @@ from open_webui.utils.middleware import (
build_chat_response_context,
process_chat_payload,
process_chat_response,
publish_chat_failed_event,
)
from open_webui.utils.misc import get_response_error_detail, merge_model_params
from open_webui.utils.model_ids import strip_provider_model_prefix
@ -1707,6 +1708,11 @@ async def chat_completion(
)
except Exception:
log.exception('Failed to emit chat error')
try:
await publish_chat_failed_event(request, user, metadata, str(error_detail))
except Exception:
log.exception('Failed to publish chat failed event')
finally:
# Clean up MCP clients. Each client is isolated so one
# failure doesn't skip the rest.

View file

@ -237,6 +237,30 @@ async def publish_chat_finished_event(
await event_emitter({'type': 'chat:list', 'data': {'chat_id': chat_id, 'folder_id': folder_id}})
async def publish_chat_failed_event(request: Request, user: UserModel, metadata: dict, error: str):
chat_id = metadata.get('chat_id')
if getattr(request.state, 'internal', False) is True or not is_saved_chat_id(chat_id):
return
webui_url = await Config.get('webui.url')
await publish_event(
request,
EVENTS.CHAT_FAILED,
actor=user,
subject_id=chat_id,
subject_type='chat',
data={
'user_id': user.id,
'chat_id': chat_id,
'message_id': metadata.get('message_id'),
'model_id': metadata.get('model_id'),
'url': f'{webui_url}/c/{chat_id}' if webui_url else f'/c/{chat_id}',
'message': error,
},
message='Chat failed',
)
# We believe in one maker of all models, seen and unseen,
# and in the reasoning which proceeds from the architect.
# We look for the resurrection of dead processes and the
@ -4361,25 +4385,7 @@ async def non_streaming_chat_response_handler(response, ctx):
response = build_response_object(response, merge_events_into_response(response_data, events))
except Exception as e:
log.debug('Error occurred while processing request: %s', e)
chat_id = metadata.get('chat_id')
if getattr(request.state, 'internal', False) is not True and chat_id and is_saved_chat_id(chat_id):
webui_url = await Config.get('webui.url')
await publish_event(
request,
EVENTS.CHAT_FAILED,
actor=user,
subject_id=chat_id,
subject_type='chat',
data={
'user_id': user.id,
'chat_id': chat_id,
'message_id': metadata.get('message_id'),
'model_id': metadata.get('model_id'),
'url': f'{webui_url}/c/{chat_id}' if webui_url else f'/c/{chat_id}',
'message': str(e),
},
message='Chat failed',
)
await publish_chat_failed_event(request, user, metadata, str(e))
pass
return response