microsoft / microsoft/simplechat
Clicking a hidden conversation in the "show hidden" view fails to open it
@paullizer is already working on this.
Since Aug 28, 2026.
- Dominant language
- Python
- Stars
- 153
- Forks
- 116
- Avg merge
- 7h 7m
- Merged PRs (30d)
- 122
Description
Summary
When a conversation is hidden and you toggle the "show hidden conversations" view (the eye button), the hidden conversation appears in the list, but clicking it does not open the conversation. The chat pane shows nothing / "Conversation not found." You have to explicitly unhide the conversation first, and only then does clicking it work.
Version observed: 0.261.002 (application/single_app/config.py)
Steps to Reproduce
- Open the chat page.
- Hide a conversation (three-dot menu → Hide).
- Click the eye / settings toggle to show hidden conversations.
- The hidden conversation is now listed.
- Click the hidden conversation.
Expected Behavior
The conversation opens and its messages load, exactly as it would if it were not hidden. Showing hidden conversations should make them fully usable, not just visible.
Actual Behavior
Nothing loads. The conversation does not open. The user has to unhide the conversation (making it a normal visible item) before clicking it works.
Root Cause Analysis
The failure is in the sidebar conversation click path.
application/single_app/static/js/chat/chat-sidebar-conversations.js (~line 676):
// If this conversation is hidden, ensure the main conversation list also shows hidden conversations
if (convo.is_hidden && window.chatConversations && window.chatConversations.setShowHiddenConversations) {
window.chatConversations.setShowHiddenConversations(true);
// Wait a moment for the DOM to update before selecting
setTimeout(() => {
setActiveConversation(convo.id);
if (window.chatConversations && window.chatConversations.selectConversation) {
window.chatConversations.selectConversation(convo.id);
}
}, 50);
}
application/single_app/static/js/chat/chat-conversations.js (~line 2617):
// Helper function to set show hidden conversations state and return a promise
export function setShowHiddenConversations(value) {
showHiddenConversations = value;
loadConversations(); // <-- not awaited, does not return the promise
}
The chain of problems:
-
setShowHiddenConversations()is documented as returning a promise but returnsundefined.loadConversations()is fire-and-forget. -
loadConversations()immediately callssetConversationListMessage('Loading conversations...'), which doesconversationsList.replaceChildren(messageEl)— every.conversation-itemis removed from the DOM while the/api/conversations/feedrequest is in flight. -
The caller then relies on a hard-coded
setTimeout(..., 50). A network round trip to the feed endpoint essentially never completes in 50 ms. -
selectConversation()(chat-conversations.js~line 1522) starts with:const convoItem = document.querySelector(`.conversation-item[data-conversation-id="${conversationId}"]`); if (!convoItem) { console.warn(`Conversation item not found for ID: ${conversationId}`); if (currentConversationTitleEl) currentConversationTitleEl.textContent = "Conversation not found"; if (chatbox) chatbox.innerHTML = '<div class="text-center p-5 text-muted">Conversation not found.</div>'; highlightSelectedConversation(null); toggleConversationInfoButton(false); hideWorkflowActivityButton(); return; // <-- bails out, never calls loadMessages() }Because the list was wiped in step 2, the lookup returns
nullandselectConversationbails out before ever callingloadMessages().
Secondary contributing factors:
setShowHiddenConversations(true)is called unconditionally even whenshowHiddenConversationsis alreadytrue(which it is, since the user just toggled the "show hidden" view). So the reload/DOM wipe is triggered for no reason on every click of a hidden conversation.loadConversations()has anisLoadingConversationsre-entrancy guard that silently returnsnullif a load is already in flight, so the "wait for it" assumption is unreliable even with a longer timeout.selectConversation()does not fall back to the existingensureConversationPresent(conversationId)helper (chat-conversations.js~line 884), which was built exactly for the "conversation isn't in the DOM list yet" case.
The backend is not at fault here — /api/conversations/<id>/metadata and /conversation/<id>/messages both serve hidden conversations normally and do not filter on is_hidden.
Suggested Fix
- Make
setShowHiddenConversations()return theloadConversations()promise (matching its own doc comment), and no-op the reload when the value is unchanged. - In the sidebar click handler, replace the
setTimeout(..., 50)withawait/.then()on that promise instead of guessing at a delay. - Harden
selectConversation()so that when the item is missing from the DOM it callsawait ensureConversationPresent(conversationId)before giving up, and only shows "Conversation not found" if that also fails. This removes the whole class of race conditions between list re-render and selection.
Impact
- Hidden conversations are effectively unreadable without unhiding them, which defeats the purpose of the "show hidden" view.
- Affects the sidebar conversation list on the chat page.
- User-visible, no data loss, no workaround other than unhiding.
Suggested Tests
functional_tests/— a test covering "select a hidden conversation while show-hidden is active loads its messages".- Regression coverage that
selectConversation()recovers viaensureConversationPresent()when the conversation item is absent from the DOM.
Related Files
application/single_app/static/js/chat/chat-sidebar-conversations.jsapplication/single_app/static/js/chat/chat-conversations.jsapplication/single_app/route_backend_conversations.py(verified not the cause)application/single_app/route_frontend_conversations.py(verified not the cause)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.