fix: silence double toasts in Loras/media custom-catch sites (#2669)#2723
Merged
Conversation
The LoRAs and Media Models pages surfaced the same failure twice: once from
request()'s default toast and again from the caller's own .catch — either a
custom toast or a persistent inline error panel.
Threads a backward-compatible trailing `options` into the six affected
apiImageVideo wrappers and passes `{ silent: true }` at each custom-catch
site, so exactly one layer reports the failure.
Refs #2669
This was referenced Jul 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
One batch of the #2669 sweep: Loras / media. Picked because it was the largest coherent remaining area that avoids the files reserved by concurrent work.
The rule applied (from the issue): a site gets
{ silent: true }when the call reaches the auto-toastingrequest()and the caller already owns its own error UI in.catch. Sites without their own error UI keep the single default helper layer.6 sites changed across 2 files, plus a backward-compatible trailing
optionsparam threaded into 6apiImageVideo.jswrappers (listLorasFull,getCivitaiSuggestions,deleteLoraFull,setCivitaiAuth,clearCivitaiAuth,listCachedModels).Loras.jsx(5) — Civitai suggestions refresh, LoRA delete, Civitai key save, Civitai key clear (all customtoast.error), plus the LoRA list load.MediaModels.jsx(1) — the cached-models list load.A note on the two list-load sites
listLorasFullandlistCachedModelscatch intosetError, which renders a persistent inline error panel (a<Banner tone="error">/ full error state) rather than a toast — so they double-report without matching atoast.error-in-.catchgrep. Included them deliberately: silencing leaves the panel, which is the better of the two surfaces, and this is not a toast-less swallow (those correctly keep the single default layer and were left alone).This isn't a new interpretation —
MediaModels.handleAddFromHfalready ships asaddMediaModelFromHf({ url, silent: true })paired with asetAddErrorcatch. The two list loads were simply missed by the same sweep.Verified-clean, no change needed
The issue's "Remaining" list called for ~9 sites here; most were already swept or are false positives. Each was checked by reading the call chain out to
request():MusicVideo.jsx,MediaJobsQueue.jsx,MediaModels.jsx(mutations),ImageGen.jsx— already passsilentat every custom-catch site.removeImageWatermark/regenerateGalleryImage— hardcodedsilent: truein the wrapper; theImageGen.jsxtoasts are already the only layer. Same forsearchCivitaiLoras(silent = truedefault), which is the Loras Civitai-search toast.ImageClean.jsx—cleanImage/fetchCleanResultuse rawfetch, neverrequest(), so nothing auto-toasts.saveCleanResultalready passessilent.getCivitaiAuth().catch(() => {}),listMediaModelRegistry().catch(() => {}),deleteImage(...).catch(() => {}),listMediaJobs(...).catch(() => null)) — left alone per the rule.Test plan
cd client && npm test— 403 files / 4387 tests passed, 0 failures (no flakes this run).useUniverseDraft.test.jsxreferences one (listLorasFull), as a barevi.fn()mock with no argument assertions. All six params default to{}, so every existing caller is unaffected.Remaining
Out-of-batch. Counts are from the issue's last scan and are not individually wrapper-verified — the stale-list problem has bitten three batches now, so re-scan before trusting them:
CreativeDirector.jsx:180,PlanTab.jsx:91/103/113,OverviewTab.jsx:148CatalogCastPanel,GmailMboxImportPanel,LocalLlmTab,MessageDetail,GenomeTab,PipelineManuscriptEditorManuscriptCommentCard.jsx:247,251—generatePipelineManuscriptFixstill needs anoptionsparamAlready shipped, do not re-sweep: settings + JIRA (#2670), messages/calendar/sharing, pipeline stages/canvas (#2714), writers-room/universe/universeBuilder/digital-twin/media pages/hooks (#2682), apps/GitHub/misc (#2721), and now Loras/media.
Refs #2669