Skip to content

Shared (multi-user) personal conversations 404 on load and never return an AI response #1281

Closed

Description

@paullizer

Issue

Once a personal conversation is shared with another user (chat_type = personal_multi_user), the conversation is unusable end to end. Two independent defects are involved:

  1. Every page reload or sidebar click on the shared conversation fires a 404 against the personal messages endpoint and raises a Conversation not found danger toast.
  2. Every AI request in the shared conversation fails immediately with Stream interrupted: Chat streaming endpoint is unavailable, so the model is never invoked.

Affects all users of the Collaborative Conversations feature.

Steps to Reproduce

  1. Start a normal personal conversation and exchange a few messages.
  2. Share it with another user (Add participants), converting it to personal_multi_user.
  3. Reload /chats, or click the conversation in the sidebar.
    • Observe the 404 and the error toast.
  4. Send a message in the shared conversation (for example @Telemetry How many TM packets have arrived since startup?).
    • Observe the stream error instead of a response.

Expected Behavior

  • Selecting or reloading a shared conversation loads its messages from the collaboration endpoint with no failed requests and no error toast.
  • Sending a message in a shared conversation streams a normal assistant response.

Actual Behavior

Console on load/select:

addChatTypeBadges: chatType="personal_multi_user", groupName="null"
GET /conversation/9f615422-.../messages?ts=... 404 (Not Found)
Error loading messages: Error: Conversation not found
    at chat-messages.js:2140
    at async selectConversation (chat-conversations.js:1688)

Chat transcript on send:

AI
Stream interrupted before any content was received.
⚠ Stream interrupted: Chat streaming endpoint is unavailable
Response may be incomplete. The partial content above has been saved.

Impact

The Collaborative Conversations feature is effectively broken for personal multi-user chats. There is no workaround — a shared conversation cannot be reloaded cleanly and cannot produce an AI response. Group collaborative conversations use the same stream bridge and are affected by the second defect as well.

Notes

Root cause 1 — personal-only endpoint used for collaborative conversations

selectConversation() in application/single_app/static/js/chat/chat-conversations.js calls loadMessages(conversationId) inside the collaborative branch:

if (isCollaborativeConversation && window.chatCollaboration?.activateConversation) {
    await loadMessages(conversationId);          // personal-only endpoint
    scrollConversationViewToBottom();
    await window.chatCollaboration.activateConversation(conversationId, metadata);
}

loadMessages() fetches /conversation/<id>/messages, whose handler (route_frontend_conversations.get_conversation_messages) only reads cosmos_conversations_container. A collaborative conversation lives in cosmos_collaboration_conversations_container under a different id than its hidden source_conversation_id (see ensure_personal_collaboration_for_legacy_conversation), so the read always raises CosmosResourceNotFoundError → 404.

The call is also redundant: activateConversation() → loadConversationMessages() already clears #chatbox and renders the collaboration messages.

Two side effects regress because of the failing call:

  • updateComparisonChatUploadCatalog([]) runs from the catch, so chat uploads in shared conversations never populate the Compare/Analyze picker.
  • updateConversationTaskDocumentsFromMessages() never runs, so task documents from the previously viewed conversation stay cached against the wrong conversation.

Root cause 2 — Blueprint migration broke the internal stream endpoint lookup

application/single_app/route_backend_collaboration.py:

internal_stream_view = current_app.view_functions.get('chat_stream_api')
if not callable(internal_stream_view):
    yield _serialize_stream_error('Chat streaming endpoint is unavailable', ...)

Commit 094424bc ("Harden route blueprint security policies") moved every route module onto Blueprints. app.py registers chat routes with register_route_blueprint('backend_chats', ...), so /api/chat/stream is now @bp.route(...) and its Flask endpoint key is backend_chats.chat_stream_api, not chat_stream_api. The lookup returns None and the collaborative stream short-circuits before the model is called.

current_app.view_functions is the only remaining blueprint-prefix assumption in the app — every url_for() call is already dotted.

Collateral

functional_tests/test_collaboration_shared_ai_workflow.py is already failing from the same Blueprint migration: it asserts @app.route('/api/collaboration/conversations/<conversation_id>/stream', ...), which is now @bp.route(...).

Suspected files

  • application/single_app/route_backend_collaboration.py
  • application/single_app/static/js/chat/chat-conversations.js
  • application/single_app/static/js/chat/chat-collaboration.js
  • application/single_app/static/js/chat/chat-messages.js
  • functional_tests/test_collaboration_shared_ai_workflow.py

Activity

  1. paullizer commented on Aug 18, 2026

    @paullizer
    CollaboratorAuthor

    Both root causes are fixed in PR #1283 (v0.250.224).

    Root cause 1 — selectConversation() called the personal loadMessages() for collaborative conversations, hitting /conversation/<id>/messages. That handler only reads cosmos_conversations_container, but a shared conversation lives in the collaboration container under a different id than its hidden source_conversation_id, so the read always 404'd. The call was redundant — activateConversation() already loads and renders the shared messages. Removed it, and moved the search highlight, task document, and comparison chat upload side effects into loadConversationMessages() so shared conversations keep parity (this also restores chat uploads in the Compare/Analyze picker and stops stale task documents carrying over).

    Root cause 2 — the collaboration stream bridge resolved the internal chat stream view by the bare name chat_stream_api, but the Blueprint security hardening moved it to backend_chats.chat_stream_api. Added a Blueprint-tolerant _resolve_internal_view_function() that keeps the exact-match fast path, plus a [COLLABORATION] log event when resolution fails so this cannot regress silently again. Group collaborative conversations are restored by the same fix.

    Validation

    • New functional test builds a Flask app registering chat_stream_api on a backend_chats Blueprint exactly like production and asserts the resolver finds it: 6/6 passed.
    • New Playwright test runs the shipped loadConversationMessages() in Chromium and asserts the personal endpoint is never requested: passed.
    • Both new tests were verified to fail against pre-fix source.
    • Route policy tests: 12/12 passed.
    • Full ui_tests/ suite went 28 → 27 failures, and functional tests referencing the changed JS went 13 → 10 — no new failures introduced; remaining ones confirmed pre-existing against stashed source.

    Follow-ups found but left out of scope (noted in the PR): _serialize_stream_error() omits conversation_kind; chat-streaming.js:1449/:1515 call a window.chatMessages.loadMessages that is not exported and are inert; and roughly 68 tests repo-wide still assert the pre-Blueprint @app.route form.

  2. added a commit that references this issue on Aug 18, 2026
    86ae8cf
  3. paullizer commented on Aug 19, 2026

    @paullizer
    CollaboratorAuthor

    Shipped in v0.250.227 via #1283 and #1288.

    Release note entries:

    • v0.250.227: Shared Conversation Stream Errors Stay Attached to the Shared Conversation
    • v0.250.227: Repaired Route Assertions Across the Test Suite
    • v0.250.224: Shared Conversations Load and Answer Again
    • v0.250.224: AI Responses Work Again in Shared Conversations
    • v0.250.224: Chat Uploads and Task Documents in Shared Conversations

    Full notes: https://microsoft.github.io/simplechat/explanation/release_notes/

    Closing as completed. This issue stayed open after the fix merged because pull requests target Development while the repository default branch is main, so GitHub never applied the Fixes # keyword automatically.

  4. moved this from Pending Evaluation to Released in Simple Chat Roadmapon Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions