[BUG] Conversation list stuck in infinite loading spinner on API failure/timeout (CLEAR_LIST_LOADING_STATUS not called in catch/finally)
Describe the bug
In the conversation dashboard, if ConversationApi.get or ConversationApi.filter fails (e.g., due to a temporary network blip, an HTTP 500/504 gateway timeout, or a slow request timeout), the conversation list in the left sidebar enters an infinite loading spinner state and never recovers.
Looking at app/javascript/dashboard/store/modules/conversations/actions.js:
fetchAllConversations: async ({ commit, state, dispatch }) => {
commit(types.SET_LIST_LOADING_STATUS);
try {
const params = state.conversationFilters;
const {
data: { data },
} = await ConversationApi.get(params);
buildConversationList(
{ commit, dispatch },
params,
data,
params.assigneeType
);
} catch (error) {
// Handle error
}
},
fetchFilteredConversations: async ({ commit, dispatch }, params) => {
commit(types.SET_LIST_LOADING_STATUS);
try {
const { data } = await ConversationApi.filter(params);
buildConversationList(
{ commit, dispatch },
params,
data,
'appliedFilters'
);
} catch (error) {
// Handle error
}
},Notice that:
commit(types.SET_LIST_LOADING_STATUS)setsgetChatListLoadingtotrue.commit(types.CLEAR_LIST_LOADING_STATUS)is only invoked insidebuildConversationList(...).- If
ConversationApi.getorConversationApi.filterrejects/throws, thecatch (error)block does nothing (// Handle error), silently swallowing the error without ever clearingtypes.SET_LIST_LOADING_STATUS.
In ConversationList.vue:
<div v-if="isLoading" class="flex justify-center my-4">
<Spinner class="text-n-brand" />
</div>Because isLoading (chatListLoading) remains true permanently, the user is stuck with a spinning blue loader in the left sidebar and an empty list of chats, even when navigating or switching between conversations, until they perform a hard page refresh (Ctrl+Shift+R).
To Reproduce
- Open Chatwoot dashboard (
/app/accounts/{id}/conversations/{id}). - Simulate a network failure or temporary 500/504 response for
GET /api/v1/accounts/{id}/conversations?...(e.g. using browser DevTools Network Request Blocking or throttling/failing the request). - Observe that the left conversation list displays a spinning loader indefinitely.
- Switching tabs or clicking does not clear the spinner because the Vuex loading state is never reset on failure.
Expected behavior
If the conversation fetch fails:
types.CLEAR_LIST_LOADING_STATUSshould always be committed (e.g., in afinallyblock or insidecatch).- An error state or retry button / alert should ideally be displayed instead of an infinite spinner.
Environment
Linux VM / Docker / All self-hosted & cloud environments.
Proposed Fix
In app/javascript/dashboard/store/modules/conversations/actions.js, ensure CLEAR_LIST_LOADING_STATUS is always executed, either in catch or via a finally block:
fetchAllConversations: async ({ commit, state, dispatch }) => {
commit(types.SET_LIST_LOADING_STATUS);
try {
const params = state.conversationFilters;
const {
data: { data },
} = await ConversationApi.get(params);
buildConversationList(
{ commit, dispatch },
params,
data,
params.assigneeType
);
} catch (error) {
commit(types.CLEAR_LIST_LOADING_STATUS);
// Optional: dispatch toast / error alert
}
},
fetchFilteredConversations: async ({ commit, dispatch }, params) => {
commit(types.SET_LIST_LOADING_STATUS);
try {
const { data } = await ConversationApi.filter(params);
buildConversationList(
{ commit, dispatch },
params,
data,
'appliedFilters'
);
} catch (error) {
commit(types.CLEAR_LIST_LOADING_STATUS);
}
},Source: chatwoot/chatwoot