Skip to content

fix(web): clear stale conversation_id from localStorage on 404#34945

Open
HamzaSwitch wants to merge 1 commit intolanggenius:mainfrom
HamzaSwitch:fix/issue-34731-stale-conversation-id
Open

fix(web): clear stale conversation_id from localStorage on 404#34945
HamzaSwitch wants to merge 1 commit intolanggenius:mainfrom
HamzaSwitch:fix/issue-34731-stale-conversation-id

Conversation

@HamzaSwitch
Copy link
Copy Markdown
Contributor

Fixes #34731.

When a conversation has been deleted on the server but the Web App chatbot still has its conversation_id in localStorage, the page enters an infinite loop: it refetches GET /api/messages?conversation_id=..., gets 404, shows a toast, and retries again every couple of seconds. The "Reset conversation" button only clears the visual state, not the localStorage entry, so the only real workaround is for the user to manually clear site data.

The reporter and @dosu already traced the root cause pretty well. Summarizing:

  1. useShareChatList in web/service/use-share.ts doesn't configure retry, so TanStack Query uses its default (3 retries) and also refetches on window focus.
  2. fetchChatList doesn't pass silent: true, so every failed attempt fires a toast via afterResponseErrorCode in web/service/fetch.ts.
  3. Both embedded-chatbot/hooks.tsx and chat-with-history/hooks.tsx destructure only data and isLoading from useShareChatList — the error state is ignored, so nothing clears the stale conversation_id from localStorage when the 404 comes back.

The fix

Three small changes, all frontend:

web/service/share.tsfetchChatList now passes silent: true so a 404 response doesn't spam toasts. The 404 is a legitimate "conversation no longer exists" signal that the hook layer handles; it shouldn't look like a server error to the user.

web/service/use-share.tsuseShareChatList now disables retries for 404s:

retry: (failureCount, error: unknown) => {
  if (error instanceof Response && error.status === 404)
    return false
  return failureCount < 3
}

Other HTTP failures still get the default 3 retries.

web/app/components/base/chat/embedded-chatbot/hooks.tsx and web/app/components/base/chat/chat-with-history/hooks.tsx — both now read error from useShareChatList and run a useEffect that calls removeConversationIdInfo(appId) when the error is a 404 Response. Clearing the stale entry causes currentConversationId to fall back to '', which in turn disables the query (since isEnabled checks !!params.conversationId), and the chatbot starts a fresh conversation.

chat-with-history/hooks.tsx didn't previously have a removeConversationIdInfo helper, so I added one matching the shape of the existing embedded-chatbot implementation.

Why this shape instead of alternatives

  • Backend fix (return 200 with an empty array on deleted conversations) — would mask real 404s and lose the useful "this id is gone" signal. The frontend already has everything it needs to handle this cleanly.
  • Reset conversation button also clears localStorage — the reporter mentioned that the button only resets the visual state. I looked at Chatflow conversation reset button does not clear conversationIdInfo, preventing new conversations #33362 which tracks that separately. Fixing the infinite-loop symptom doesn't require touching the button, and wiring both into one PR would widen scope.
  • Suppressing the toast only, without retry/clear logic — would stop the visible spam but leave the underlying retry storm running in the network tab. The retry stop + localStorage clear is what actually makes the page recover.

Testing

Manually reproduced on a self-hosted stack (docker compose -p dify up -d) with a Chatflow app exposed as a Web App:

  1. Opened the chatbot URL, sent a message, confirmed conversationIdInfo is populated in Application → Local Storage → conversationIdInfo.
  2. Deleted the conversation from the console as admin.
  3. Reloaded the chatbot page.

Before the fix: Network tab shows GET /api/messages?... returning 404 every 2–3 seconds, toast error pops up repeatedly, page never recovers. Clicking "Reset conversation" does nothing useful.

After the fix: Exactly one GET /api/messages?... 404 in the network tab, no toast, conversationIdInfo is cleared from localStorage on the same tick, the chatbot falls back to the new-conversation state automatically.

Also re-tested the happy path (send messages in a valid conversation, switch conversations, refresh) to confirm I didn't break the normal chat-list loading flow.

When a Web App chatbot conversation is deleted server-side, the client
would enter an infinite retry loop of 404s on GET /api/messages. The
stale conversation_id in localStorage was never cleared, and TanStack
Query kept retrying (3x per cycle) on every window focus.

- useShareChatList now disables retries for 404 responses
- fetchChatList passes silent: true so the 404 does not spam toasts
- Both embedded-chatbot and chat-with-history hooks now watch the
  error state and clear the stale conversation_id via
  removeConversationIdInfo(appId) when the 404 is observed, which
  disables the query and falls back to a fresh conversation

Fixes langgenius#34731
@github-actions github-actions bot added web This relates to changes on the web. needs-revision labels Apr 10, 2026
@dosubot
Copy link
Copy Markdown

dosubot bot commented Apr 10, 2026

Hi @HamzaSwitch! I'm Dosu and I’m helping the dify team.

This is a clean, well-scoped fix. The three-pronged approach — suppress toast with silent: true, stop retries on 404, and clear the stale conversation_id from localStorage — addresses the exact root cause traced in #34731 and matches the fix strategy that was recommended there.

A few observations:

One thing worth double-checking: in the useEffect that clears localStorage on 404, make sure the dependency array includes error (and appId if used) so the effect doesn't run stale. From the description it sounds like this is already the case, but it's the main thing a reviewer should verify in the diff.

Overall this looks good to me — minimal surface area, well-tested, and directly addresses the infinite-loop symptom without masking errors or widening scope. 👍

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
Chat with Dosu Open in Cursor  Share on X

@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. javascript Pull requests that update javascript code labels Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

javascript Pull requests that update javascript code needs-revision size:M This PR changes 30-99 lines, ignoring generated files. web This relates to changes on the web.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stale conversation_id in localStorage causes infinite 404 "Conversation Not Exists" loop in Web App chatbot

1 participant