dify - ✅(Solved) Fix Stale conversation_id in localStorage causes infinite 404 "Conversation Not Exists" loop in Web App chatbot [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
langgenius/dify#34731Fetched 2026-04-09 08:18:03
View on GitHub
Comments
1
Participants
2
Timeline
3
Reactions
1
Author
Participants
Timeline (top)
labeled ×2commented ×1

Error Message

  1. useShareChatList in web/service/use-share.ts has no 404 error handling — TanStack Query retries 3 times by default, and refetches on window focus, creating an infinite retry loop for this unrecoverable error. When a conversation is deleted, the Web App chatbot enters an infinite 404 error loop. The user sees the error message "Conversation Not Exists. You have requested this URI [/api/messages] but did you mean /api/messages or /api/chat-messages or /api/saved-messages?" every 2-3 seconds. Clicking "Reset conversation" does not fix it. The only workaround is for the user to manually clear browser localStorage/site data for the domain.

Root Cause

Root Cause Analysis The issue spans two areas:

  1. useShareChatList in web/service/use-share.ts has no 404 error handling — TanStack Query retries 3 times by default, and refetches on window focus, creating an infinite retry loop for this unrecoverable error.
  2. Both chat-with-history/hooks.tsx and embedded-chatbot/hooks.tsx use useLocalStorageState to persist conversation_id. When GET /api/messages returns 404, neither hook clears the stale conversation_id from localStorage or resets to a new conversation state. The "Reset conversation" button only resets the visual state but does not clear the localStorage entry.

Fix Action

Fix / Workaround

When a conversation is deleted, the Web App chatbot enters an infinite 404 error loop. The user sees the error message "Conversation Not Exists. You have requested this URI [/api/messages] but did you mean /api/messages or /api/chat-messages or /api/saved-messages?" every 2-3 seconds. Clicking "Reset conversation" does not fix it. The only workaround is for the user to manually clear browser localStorage/site data for the domain.

PR fix notes

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

Description (problem / solution / changelog)

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 #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.

Changed files

  • web/app/components/base/chat/chat-with-history/hooks.tsx (modified, +16/-1)
  • web/app/components/base/chat/embedded-chatbot/hooks.tsx (modified, +9/-1)
  • web/service/share.ts (modified, +4/-1)
  • web/service/use-share.ts (modified, +8/-0)

PR #35003: fix: clear stale conversation_id on 404 to prevent infinite retry loop

Description (problem / solution / changelog)

Summary

When a conversation is deleted server-side, the Web App chatbot entered an infinite 404 error loop because the stale conversation_id persisted in localStorage and TanStack Query kept retrying.

  • Added a retry function to useShareChatList that skips retries on 404 responses (unrecoverable errors)
  • Added a useEffect in both chat-with-history/hooks.tsx and embedded-chatbot/hooks.tsx to detect 404 errors and clear the stale conversation_id from localStorage, resetting to a new conversation state

Fixes #34731

Screenshots

N/A — logic-only change, no visual changes.

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran make lint and make type-check (backend) and cd web && pnpm exec vp staged (frontend) to appease the lint gods

From Claude Code

Changed files

  • web/app/components/base/chat/chat-with-history/hooks.tsx (modified, +7/-1)
  • web/app/components/base/chat/embedded-chatbot/hooks.tsx (modified, +7/-1)
  • web/service/use-share.ts (modified, +7/-0)
RAW_BUFFERClick to expand / collapse

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

v1.13.3

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

Steps to reproduce

  1. Deploy Dify with a Chatflow app and share it as a Web App (e.g. via /chatbot/<app_code> embed URL)
  2. Open the chatbot URL in a browser, send some messages to create a conversation
  3. Observe in browser DevTools → Application → Local Storage that conversationIdInfo now stores the conversation_id
  4. Delete the conversation from Dify (e.g. admin deletes it via console, or the conversation is removed from the database)
  5. Reload the chatbot page in the browser Nginx access log confirms the loop — the same stale conversation_id is retried every 2-3 seconds, all returning 404: GET /api/messages?conversation_id=xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx06060&limit=20&last_id= HTTP/1.1" 404 201 GET /api/messages?conversation_id=xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx06060&limit=20&last_id= HTTP/1.1" 404 201 GET /api/messages?conversation_id=xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx06060&limit=20&last_id= HTTP/1.1" 404 201 ... (repeated 28+ times)
  6. Clicking "Reset conversation" in the UI does not resolve the issue.

Root Cause Analysis The issue spans two areas:

  1. useShareChatList in web/service/use-share.ts has no 404 error handling — TanStack Query retries 3 times by default, and refetches on window focus, creating an infinite retry loop for this unrecoverable error.
  2. Both chat-with-history/hooks.tsx and embedded-chatbot/hooks.tsx use useLocalStorageState to persist conversation_id. When GET /api/messages returns 404, neither hook clears the stale conversation_id from localStorage or resets to a new conversation state. The "Reset conversation" button only resets the visual state but does not clear the localStorage entry.

✔️ Expected Behavior

When a conversation no longer exists (API returns 404), the frontend should automatically detect the stale conversation_id, clear it from localStorage, and reset to a new conversation state — providing a seamless user experience without requiring manual browser data clearing.

❌ Actual Behavior

When a conversation is deleted, the Web App chatbot enters an infinite 404 error loop. The user sees the error message "Conversation Not Exists. You have requested this URI [/api/messages] but did you mean /api/messages or /api/chat-messages or /api/saved-messages?" every 2-3 seconds. Clicking "Reset conversation" does not fix it. The only workaround is for the user to manually clear browser localStorage/site data for the domain.

extent analysis

TL;DR

Implement 404 error handling in useShareChatList and clear stale conversation IDs from localStorage when a conversation no longer exists.

Guidance

  • Modify useShareChatList in web/service/use-share.ts to handle 404 errors and prevent infinite retries.
  • Update chat-with-history/hooks.tsx and embedded-chatbot/hooks.tsx to clear the conversation ID from localStorage when a 404 error occurs.
  • Consider adding a check for stale conversation IDs on page load to prevent the infinite retry loop.
  • Verify that the "Reset conversation" button clears the localStorage entry and resets the conversation state.

Example

// web/service/use-share.ts
import { useQuery } from '@tanstack/react-query';

const useShareChatList = () => {
  const { data, error, isLoading } = useQuery(
    ['shareChatList'],
    async () => {
      const response = await fetch('/api/messages');
      if (response.status === 404) {
        // Clear conversation ID from localStorage
        localStorage.removeItem('conversationIdInfo');
        throw new Error('Conversation not found');
      }
      return response.json();
    },
    {
      retry: 0, // Disable retries for 404 errors
    }
  );

  if (error && error.status === 404) {
    // Handle 404 error and reset conversation state
  }

  return { data, error, isLoading };
};

Notes

The provided solution assumes that the useShareChatList hook is the primary cause of the infinite retry loop. Additional modifications may be necessary to ensure a seamless user experience.

Recommendation

Apply the workaround by implementing 404 error handling in useShareChatList and clearing stale conversation IDs from localStorage. This should prevent the infinite retry loop and provide a better user experience.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

dify - ✅(Solved) Fix Stale conversation_id in localStorage causes infinite 404 "Conversation Not Exists" loop in Web App chatbot [2 pull requests, 1 comments, 2 participants]