Skip to content

🐛fix: prevent duplicate toast notifications#2403

Open
prakharsingh-74 wants to merge 4 commits intokubestellar:devfrom
prakharsingh-74:BUG/toast-notification
Open

🐛fix: prevent duplicate toast notifications#2403
prakharsingh-74 wants to merge 4 commits intokubestellar:devfrom
prakharsingh-74:BUG/toast-notification

Conversation

@prakharsingh-74
Copy link

Description

Duplicate toast notifications were appearing when users encountered errors, particularly "Access denied" messages. The same error would trigger 2-3 identical toasts simultaneously, degrading the user experience.

Fixes #2185

Changes Made

Root Cause
Multiple layers of error handling were independently triggering toast notifications:

  • QueryCache Handler (queryClient.ts) - Did NOT use unique IDs
  • MutationCache Handler (queryClient.ts) - Did NOT use unique IDs
    When an error occurred (e.g., 403 Forbidden), all three handlers would fire, creating duplicate toasts for the same error.

Checklist

Please ensure the following before submitting your PR:

  • I have reviewed the project's contribution guidelines.
  • I have tested the changes locally and ensured they work as expected.
  • My code follows the project's coding standards.

Screenshots or Logs (if applicable)

Before
image

After
image

@kubestellar-prow kubestellar-prow bot added the dco-signoff: no Indicates the PR's author has not signed the DCO. label Jan 22, 2026
@github-actions
Copy link
Contributor

Welcome to KubeStellar! 🚀 Thank you for submitting this Pull Request.

Before your PR can be merged, please ensure:

DCO Sign-off - All commits must be signed off with git commit -s to certify the Developer Certificate of Origin

PR Title - Must start with an emoji: ✨ (feature), 🐛 (bug fix), 📖 (docs), 🌱 (infra/tests), ⚠️ (breaking change)

Getting Started with KubeStellar:

Contributor Resources:


🌟 Help KubeStellar Grow - We Need Adopters!

Our roadmap is driven entirely by adopter feedback. Whether you're using KubeStellar yourself or know someone who could benefit from multi-cluster Kubernetes:

📋 Take our Multi-Cluster Survey - Share your use cases and help shape our direction!


A maintainer will review your PR soon. Feel free to ask questions in the comments or on Slack!

@kubestellar-prow kubestellar-prow bot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Jan 22, 2026
@kubestellar-prow
Copy link

Hi @prakharsingh-74. Thanks for your PR.

I'm waiting for a kubestellar member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Signed-off-by: prakharsingh-74 <prakharsingh7014@gmail.com>
@kubestellar-prow kubestellar-prow bot added dco-signoff: yes Indicates the PR's author has signed the DCO. and removed dco-signoff: no Indicates the PR's author has not signed the DCO. labels Jan 22, 2026
@prakharsingh-74 prakharsingh-74 changed the title fix: prevent duplicate toast notifications 🐛fix: prevent duplicate toast notifications Jan 24, 2026
@prakharsingh-74
Copy link
Author

@MAVRICK-1 can you please review this PR

@prakharsingh-74
Copy link
Author

@oksaumya can you please review this

Copilot AI review requested due to automatic review settings February 15, 2026 16:02
@kubestellar-prow
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign mavrick-1 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to prevent duplicate error toast notifications by adding stable id values to the global React Query QueryCache and MutationCache error handlers.

Changes:

  • Add id options to toast.error(...) calls in QueryCache.onError to dedupe repeated query error toasts.
  • Add id options to toast.error(...) calls in MutationCache.onError to dedupe repeated mutation error toasts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +61 to 64
toast.error('Server error. Please try again later.', { id: 'mutation-error-500' });
} else {
toast.error('An error occurred while updating data');
toast.error('An error occurred while updating data', { id: `mutation-error-${status || 'unknown'}` });
}
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MutationCache has the same network-error duplication risk as QueryCache: when axios.isAxiosError(error) but there is no error.response, this will show the generic "updating data" toast while the global network error toast is displayed via NetworkErrorToastManager. Consider an early return for !error.response (or otherwise aligning with the global network-error handling) to avoid double toasts on connectivity failures.

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +29
toast.error('Authentication required. Please log in again.', { id: 'query-error-401' });
}
} else if (status === 403) {
toast.error("Access denied. You don't have permission for this action.");
toast.error("Access denied. You don't have permission for this action.", { id: 'query-error-403' });
} else if (status && status >= 500) {
toast.error('Server error. Please try again later.');
toast.error('Server error. Please try again later.', { id: 'query-error-500' });
} else {
toast.error('An error occurred while fetching data');
toast.error('An error occurred while fetching data', { id: `query-error-${status || 'unknown'}` });
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These toast IDs are scoped to query-error-*, but the Axios response interceptor also shows error toasts with IDs like api-error-${status} (see frontend/src/lib/api.ts). If a request is made via the api client (common in hooks), both the interceptor and this QueryCache handler will still fire and produce duplicate toasts because the IDs don’t match. Consider either (a) suppressing QueryCache toasts for Axios errors handled by the interceptor, or (b) using the same ID scheme (and ideally the same message source) so the toast is deduped across layers.

Copilot uses AI. Check for mistakes.
Comment on lines +27 to 30
toast.error('Server error. Please try again later.', { id: 'query-error-500' });
} else {
toast.error('An error occurred while fetching data');
toast.error('An error occurred while fetching data', { id: `query-error-${status || 'unknown'}` });
}
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Axios errors with no response (e.g., network outage), status is undefined and this falls into the generic branch, showing a toast with id query-error-unknown. At the same time, the Axios interceptor sets setGlobalNetworkError(true) and NetworkErrorToastManager shows its own network-error toast, leading to duplicates. Consider explicitly detecting axios.isAxiosError(error) && !error.response here and returning early (or routing to the same global network-error UX) instead of showing an additional generic toast.

Copilot uses AI. Check for mistakes.
Comment on lines +56 to 64
toast.error('Authentication required. Please log in again.', { id: 'mutation-error-401' });
}
} else if (status === 403) {
toast.error("Access denied. You don't have permission for this action.");
toast.error("Access denied. You don't have permission for this action.", { id: 'mutation-error-403' });
} else if (status && status >= 500) {
toast.error('Server error. Please try again later.');
toast.error('Server error. Please try again later.', { id: 'mutation-error-500' });
} else {
toast.error('An error occurred while updating data');
toast.error('An error occurred while updating data', { id: `mutation-error-${status || 'unknown'}` });
}
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same dedupe issue as QueryCache: these IDs are mutation-error-*, but requests using the shared Axios api client will also trigger the interceptor toast (api-error-${status}), so duplicates can still occur across layers because the IDs differ. Consider reusing the interceptor’s ID scheme (or suppressing one of the two toasting layers) so a single toast is shown per error.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. frontend needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/S Denotes a PR that changes 10-29 lines, ignoring generated files.

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

[Bug]: Duplicate toast notification appears on login after login ad User

2 participants