fix: handle chat_id=None in event emitter and Drive client

Two runtime regressions surfaced from server-to-server callers (tools,
automations, llm_council) hitting /api/chat/completions without a
chat_id, plus one missed await on the async OAuthSessions API.

1) socket/main.py get_event_emitter
   - request_info.get('chat_id', '').startswith(...) returned None when
     chat_id was explicitly None (dict.get default only applies when the
     key is missing entirely), causing 'NoneType' object has no attribute
     'startswith' and a 400 on every tool-driven completion request.
   - Use `(chat_id or '')` for both startswith calls.

2) utils/middleware.py background_tasks_handler
   - Same pattern: tightened the chat_id presence check from
     `'chat_id' in metadata` (False-positive on None values) to
     `metadata.get('chat_id')`. Also defensively switched two existing
     `metadata.get('chat_id', '').startswith(...)` checks to use the
     `or ''` pattern.

3) utils/google_drive_client.py create_drive_client_for_user
   - OAuthSessions.get_session_by_provider_and_user_id is now async
     (v0.9.5); the missing await produced
     "'coroutine' object has no attribute 'id'" when accessing
     .id on the returned coroutine and prevented all Drive sync runs.

Made-with: Cursor
This commit is contained in:
PVBLIC Foundation
2026-05-11 14:20:18 -07:00
parent c3ead772f1
commit 1cbfa1be06
3 changed files with 13 additions and 10 deletions
+6 -3
View File
@@ -898,8 +898,11 @@ async def _make_channel_emitter(request_info):
async def get_event_emitter(request_info, update_db=True): async def get_event_emitter(request_info, update_db=True):
# Channel mode: route pipeline output to channel message updates # Channel mode: route pipeline output to channel message updates.
if request_info.get('chat_id', '').startswith('channel:'): # Use `or ''` because callers may pass chat_id=None (server-to-server API
# callers like tools/automations); dict.get default only kicks in when
# the key is missing entirely.
if (request_info.get('chat_id') or '').startswith('channel:'):
return await _make_channel_emitter(request_info) return await _make_channel_emitter(request_info)
async def __event_emitter__(event_data): async def __event_emitter__(event_data):
@@ -917,7 +920,7 @@ async def get_event_emitter(request_info, update_db=True):
room=f'user:{user_id}', room=f'user:{user_id}',
) )
if update_db and message_id and not request_info.get('chat_id', '').startswith('local:'): if update_db and message_id and not (request_info.get('chat_id') or '').startswith('local:'):
event_type = event_data.get('type') event_type = event_data.get('type')
if event_type == 'status': if event_type == 'status':
@@ -680,7 +680,7 @@ async def create_drive_client_for_user(
from open_webui.models.oauth_sessions import OAuthSessions from open_webui.models.oauth_sessions import OAuthSessions
# Get Google OAuth session # Get Google OAuth session
oauth_session = OAuthSessions.get_session_by_provider_and_user_id("google", user_id) oauth_session = await OAuthSessions.get_session_by_provider_and_user_id("google", user_id)
if not oauth_session: if not oauth_session:
log.warning(f"No Google OAuth session for user {user_id}") log.warning(f"No Google OAuth session for user {user_id}")
return None return None
+6 -6
View File
@@ -3060,7 +3060,7 @@ async def background_tasks_handler(ctx):
messages = [] messages = []
if ( if (
'chat_id' in metadata metadata.get('chat_id')
and not metadata['chat_id'].startswith('local:') and not metadata['chat_id'].startswith('local:')
and not metadata['chat_id'].startswith('channel:') and not metadata['chat_id'].startswith('channel:')
): ):
@@ -3143,8 +3143,8 @@ async def background_tasks_handler(ctx):
} }
) )
if not metadata.get('chat_id', '').startswith('local:') and not metadata.get( if not (metadata.get('chat_id') or '').startswith('local:') and not (
'chat_id', '' metadata.get('chat_id') or ''
).startswith('channel:'): ).startswith('channel:'):
await Chats.upsert_message_to_chat_by_id_and_message_id( await Chats.upsert_message_to_chat_by_id_and_message_id(
metadata['chat_id'], metadata['chat_id'],
@@ -3157,9 +3157,9 @@ async def background_tasks_handler(ctx):
except Exception as e: except Exception as e:
pass pass
if not metadata.get('chat_id', '').startswith('local:') and not metadata.get('chat_id', '').startswith( if not (metadata.get('chat_id') or '').startswith('local:') and not (
'channel:' metadata.get('chat_id') or ''
): # Only update titles and tags for non-temp chats ).startswith('channel:'): # Only update titles and tags for non-temp chats
if TASKS.TITLE_GENERATION in tasks: if TASKS.TITLE_GENERATION in tasks:
user_message = get_last_user_message(messages) user_message = get_last_user_message(messages)
if user_message and len(user_message) > 100: if user_message and len(user_message) > 100: