Skip to content

fix(web): suppress global error toast on mutations that own their toast UX#1385

Closed
voidborne-d wants to merge 1 commit into
MODSetter:mainfrom
voidborne-d:fix/suppress-global-error-toast-mutations
Closed

fix(web): suppress global error toast on mutations that own their toast UX#1385
voidborne-d wants to merge 1 commit into
MODSetter:mainfrom
voidborne-d:fix/suppress-global-error-toast-mutations

Conversation

@voidborne-d
Copy link
Copy Markdown

@voidborne-d voidborne-d commented May 12, 2026

Closes #1371.

Summary

surfsense_web/lib/query-client/client.ts configures a global MutationCache.onError that calls showErrorToast(error) for every failed mutation unless mutation.meta?.suppressGlobalErrorToast is true. The opt-out hook was defined in the consumer but had zero producers anywhere in the codebase — every mutation atom that already had its own onError: toast.error(...) was double-toasting on failure.

This PR activates the seam: it adds meta: { suppressGlobalErrorToast: true } to exactly the mutation atoms that own their own error toast, so the global handler skips them.

Files touched (9 atom files, 30 mutations)

File Mutations
atoms/prompts/prompts-mutation.atoms.ts 4
atoms/invites/invites-mutation.atoms.ts 4
atoms/chat-comments/comments-mutation.atoms.ts 4
atoms/new-llm-config/new-llm-config-mutation.atoms.ts 4
atoms/members/members-mutation.atoms.ts 3
atoms/roles/roles-mutation.atoms.ts 3
atoms/image-gen-config/image-gen-config-mutation.atoms.ts 3
atoms/vision-llm-config/vision-llm-config-mutation.atoms.ts 3
atoms/public-chat-snapshots/public-chat-snapshots-mutation.atoms.ts 2

Total: +30/-0 across 9 files.

Atoms intentionally left alone

These mutation atoms don't have their own `onError` toast and continue to rely on the global handler — touching them would invert their UX:

  • `atoms/auth/auth-mutation.atoms.ts`
  • `atoms/user/user-mutation.atoms.ts`
  • `atoms/search-spaces/search-space-mutation.atoms.ts`
  • `atoms/logs/log-mutation.atoms.ts`
  • `atoms/documents/document-mutation.atoms.ts`
  • `atoms/connectors/connector-mutation.atoms.ts`

Why no TypeScript module augmentation

The issue mentioned augmentation might be needed via TanStack Query's `Register.mutationMeta`. In v5 (`@tanstack/react-query@^5.90.7`), `meta` is typed as `Record<string, unknown> | undefined` by default, so the producer side compiles cleanly today. The consumer (`client.ts:18-22`) already uses optional chaining (`mutation.meta?.suppressGlobalErrorToast`) which is safe against the `unknown` value type.

Adding the module augmentation would tighten the contract on both sides but isn't required for this fix to work. Happy to layer it in as a follow-up if maintainers prefer that.

Local validation

  • `pnpm biome check` on the 9 touched files: clean (no fixes applied, 0 diagnostics).

  • `tsc --noEmit` baseline before this PR: 48 errors. After this PR: 48 errors. None of the 48 are in the touched files (all are pre-existing issues in blog/dashboard/components — unrelated). Zero new TypeScript errors introduced.

  • Each mutation now matches the canonical shape from issue Stop double-toasting on mutation errors: set meta.suppressGlobalErrorToast on mutations with their own onError toast #1371:

    ```ts
    export const createPromptMutationAtom = atomWithMutation(() => ({
    mutationKey: ["prompts", "create"],
    meta: { suppressGlobalErrorToast: true }, // <-- added
    mutationFn: async (request: PromptCreateRequest) => promptsApiService.create(request),
    onSuccess: () => { ... },
    onError: (error: Error) => {
    toast.error(error.message || "Failed to create prompt");
    },
    }));
    ```

Test plan

  • Open Settings → Prompts; block the network in DevTools; attempt to create a prompt.
  • Verify exactly one error toast (`"Failed to create prompt"`) appears, not two.
  • Repeat against any flow whose mutation lives in one of the 9 modified files (e.g. invite create, role create, comment create, vision-LLM-config update).
  • Verify success-path toasts in those flows are unchanged.
  • Verify atoms in the "left alone" set still get exactly one toast on failure (from the global handler) — e.g. login failure, log create failure.

Notes

  • Followed the issue's recommended scope ("only the affected mutation atoms"); did not delete the local `onError` handlers or rework messaging — that was explicitly called out as a separate UX decision.
  • 30 mutations is the full set of atom-defined producers with a local error toast. If new mutation atoms with their own error toast get added later, they'll need the same `meta` flag — worth documenting in CONTRIBUTING.md as a follow-up.

Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com

High-level PR Summary

This PR fixes a double-toasting bug where mutation errors were being displayed twice: once from the global error handler and once from mutation-specific error handlers. The fix adds meta: { suppressGlobalErrorToast: true } to 30 mutation atoms across 9 files that already have their own onError toast handlers, activating an existing but unused opt-out mechanism in the global mutation cache. Mutations without their own error handlers continue to rely on the global handler as before.

⏱️ Estimated Review Time: 5-15 minutes

💡 Review Order Suggestion
Order File Path
1 surfsense_web/atoms/prompts/prompts-mutation.atoms.ts
2 surfsense_web/atoms/invites/invites-mutation.atoms.ts
3 surfsense_web/atoms/chat-comments/comments-mutation.atoms.ts
4 surfsense_web/atoms/members/members-mutation.atoms.ts
5 surfsense_web/atoms/roles/roles-mutation.atoms.ts
6 surfsense_web/atoms/public-chat-snapshots/public-chat-snapshots-mutation.atoms.ts
7 surfsense_web/atoms/new-llm-config/new-llm-config-mutation.atoms.ts
8 surfsense_web/atoms/image-gen-config/image-gen-config-mutation.atoms.ts
9 surfsense_web/atoms/vision-llm-config/vision-llm-config-mutation.atoms.ts

Need help? Join our Discord

Summary by CodeRabbit

  • Chores
    • Refined mutation configurations across comments, image generation, invites, members, LLM configurations, prompts, chat snapshots, roles, and vision features to provide more granular control over error notification handling during operations.

Review Change Stack

…st UX

Closes MODSetter#1371.

`surfsense_web/lib/query-client/client.ts` configures a global
`MutationCache.onError` that shows an error toast for every failed
mutation unless `meta.suppressGlobalErrorToast` is set. The opt-out
hook existed in the consumer but had zero producers — every mutation
atom that already had its own `onError: toast.error(...)` was
double-toasting on failure.

Add `meta: { suppressGlobalErrorToast: true }` to the 30 mutations
across 9 atom files that own their own error toast:

- atoms/prompts/prompts-mutation.atoms.ts (4)
- atoms/invites/invites-mutation.atoms.ts (4)
- atoms/chat-comments/comments-mutation.atoms.ts (4)
- atoms/new-llm-config/new-llm-config-mutation.atoms.ts (4)
- atoms/members/members-mutation.atoms.ts (3)
- atoms/roles/roles-mutation.atoms.ts (3)
- atoms/image-gen-config/image-gen-config-mutation.atoms.ts (3)
- atoms/vision-llm-config/vision-llm-config-mutation.atoms.ts (3)
- atoms/public-chat-snapshots/public-chat-snapshots-mutation.atoms.ts (2)

Atoms that rely on the global handler (no local `onError` toast) are
left untouched: auth, user, search-spaces, logs, documents, connectors.

TanStack Query v5 types `meta` as `Record<string, unknown> | undefined`
so no module augmentation is needed; `tsc --noEmit` reports the same
48 pre-existing errors before and after this change (none in the
touched files) and `biome check` on the 9 files passes clean.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 12, 2026

@voidborne-d is attempting to deploy a commit to the Rohan Verma's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3cef685a-f024-4148-9ef6-cb852f08e938

📥 Commits

Reviewing files that changed from the base of the PR and between d6618b8 and 2a5dcf7.

📒 Files selected for processing (9)
  • surfsense_web/atoms/chat-comments/comments-mutation.atoms.ts
  • surfsense_web/atoms/image-gen-config/image-gen-config-mutation.atoms.ts
  • surfsense_web/atoms/invites/invites-mutation.atoms.ts
  • surfsense_web/atoms/members/members-mutation.atoms.ts
  • surfsense_web/atoms/new-llm-config/new-llm-config-mutation.atoms.ts
  • surfsense_web/atoms/prompts/prompts-mutation.atoms.ts
  • surfsense_web/atoms/public-chat-snapshots/public-chat-snapshots-mutation.atoms.ts
  • surfsense_web/atoms/roles/roles-mutation.atoms.ts
  • surfsense_web/atoms/vision-llm-config/vision-llm-config-mutation.atoms.ts

📝 Walkthrough

Walkthrough

This PR systematically adds meta: { suppressGlobalErrorToast: true } to 30 mutation atoms across nine feature domains. Each mutation that implements its own onError toast handler is marked to prevent duplicate error toasts from the global MutationCache error handler.

Changes

Global Error Toast Suppression Across Mutation Atoms

Layer / File(s) Summary
Chat Comments Mutations
surfsense_web/atoms/chat-comments/comments-mutation.atoms.ts
Four comment and reply mutations add meta: { suppressGlobalErrorToast: true } to prevent global error toast duplication.
Image Generation Config Mutations
surfsense_web/atoms/image-gen-config/image-gen-config-mutation.atoms.ts
Three image generation config mutations add meta: { suppressGlobalErrorToast: true } to prevent global error toast duplication.
Invite Mutations
surfsense_web/atoms/invites/invites-mutation.atoms.ts
Four invite mutations add meta: { suppressGlobalErrorToast: true } to prevent global error toast duplication.
Member Mutations
surfsense_web/atoms/members/members-mutation.atoms.ts
Three member mutations add meta: { suppressGlobalErrorToast: true } to prevent global error toast duplication.
LLM Configuration Mutations
surfsense_web/atoms/new-llm-config/new-llm-config-mutation.atoms.ts
Four LLM config mutations add meta: { suppressGlobalErrorToast: true } to prevent global error toast duplication.
Prompt Mutations
surfsense_web/atoms/prompts/prompts-mutation.atoms.ts
Four prompt mutations add meta: { suppressGlobalErrorToast: true } to prevent global error toast duplication.
Public Chat Snapshot Mutations
surfsense_web/atoms/public-chat-snapshots/public-chat-snapshots-mutation.atoms.ts
Two public chat snapshot mutations add meta: { suppressGlobalErrorToast: true } to prevent global error toast duplication.
Role Mutations
surfsense_web/atoms/roles/roles-mutation.atoms.ts
Three role mutations add meta: { suppressGlobalErrorToast: true } to prevent global error toast duplication.
Vision LLM Configuration Mutations
surfsense_web/atoms/vision-llm-config/vision-llm-config-mutation.atoms.ts
Three vision LLM config mutations add meta: { suppressGlobalErrorToast: true } to prevent global error toast duplication.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A dozen mutations, all wearing their toast,
Now marked to hush the global ghost,
No more double-dinging in the night,
Just one sweet error—done just right! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: adding suppressGlobalErrorToast flag to mutations that own their error toast UI.
Linked Issues check ✅ Passed All coding requirements from issue #1371 are met: meta: { suppressGlobalErrorToast: true } added to 30 mutations across 9 files that own their onError toast handlers.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue; only the specified mutation atoms were modified with the meta flag, and intentionally untouched atoms remain unchanged.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@MODSetter
Copy link
Copy Markdown
Owner

@voidborne-d Thanks. Please raise PR on dev branch.

@voidborne-d
Copy link
Copy Markdown
Author

Thanks @MODSetter — retargeted onto dev as #1397 (identical patch, clean apply on dev HEAD).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stop double-toasting on mutation errors: set meta.suppressGlobalErrorToast on mutations with their own onError toast

2 participants