{"record":{"id":"8a44abf807b3b4c3","repo":"RocketChat/Rocket.Chat","slug":"banner-not-found","errorCode":null,"errorMessage":"Banner not found","messagePattern":"Banner not found","errorType":"exception","errorClass":"Error","httpStatus":500,"severity":"warning","filePath":"apps/meteor/server/modules/core-apps/cloudAnnouncements.module.ts","lineNumber":76,"sourceCode":"\t\tif (!userId) {\n\t\t\tthrow new Error('invalid user');\n\t\t}\n\n\t\tif (!id && !viewId) {\n\t\t\tthrow new Error('invalid view');\n\t\t}\n\n\t\tif (!payload.triggerId) {\n\t\t\tthrow new Error('invalid triggerId');\n\t\t}\n\n\t\t// For backwards compatibility: we prefer to use viewId, but some legacy banners\n\t\t// may only have id. We fetch all matching banners and prioritize viewId match.\n\t\tconst bannerIds = [viewId, id].filter((bannerId) => isTruthy(bannerId));\n\t\tconst banners = await Banners.findByIds(bannerIds).toArray();\n\t\tconst announcement = banners.find((b) => b._id === viewId) || banners.find((b) => b._id === id);\n\t\tif (!announcement) {\n\t\t\tthrow new Error('Banner not found');\n\t\t}\n\n\t\tawait Banner.dismiss(userId, announcement._id);\n\n\t\tconst type = announcement.surface === 'banner' ? 'banner.close' : 'modal.close';\n\n\t\t// for viewClosed we just need to let Cloud know that the banner was closed, no need to wait for the response\n\n\t\tvoid this.handlePayload(payload);\n\n\t\treturn {\n\t\t\ttype,\n\t\t\ttriggerId: payload.triggerId,\n\t\t\tappId: payload.appId,\n\t\t\tviewId: announcement._id,\n\t\t};\n\t}\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/modules/core-apps/cloudAnnouncements.module.ts#L58-L94","documentation":"`CloudAnnouncementsModule.viewClosed` resolves candidate ids `[viewId, id]`, queries `Banners.findByIds(bannerIds)`, and picks the first record matching `viewId` (or `id` for legacy banners). If none of the candidates exist in the Banners collection it throws `Error('Banner not found')`, meaning the referenced announcement banner no longer exists locally — it expired, was removed by a cloud sync, or the client sent a stale/wrong id.","triggerScenarios":"Dismissing a cloud announcement whose `_id` is not in the local Banners collection — e.g. the announcement expired or was replaced between render and close; a duplicate dismiss after the banner was already deregistered; a payload where viewId and id both point at nonexistent records.","commonSituations":"Stale clients after a workspace reconnect or cloud announcements refresh; announcements with a short validity window; multiple tabs dismissing the same banner; custom code guessing banner ids.","solutions":["Re-fetch the current banners for the user and dismiss using the live banner `_id`.","Verify existence before dismissing: `await Banners.findByIds([viewId, id].filter(Boolean)).toArray()`.","Treat this error as benign when the banner was legitimately removed (expired/already dismissed) and drop the interaction."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { Banners } from '@rocket.chat/models';\nimport { isTruthy } from '@rocket.chat/tools';\n\nconst bannerIds = [viewId, id].filter(isTruthy);\nconst banners = await Banners.findByIds(bannerIds).toArray();\nif (!banners.length) {\n  // banner already removed/expired: skip dismissal\n} else {\n  await announcementsModule.viewClosed(payload);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await announcementsModule.viewClosed(payload);\n} catch (error) {\n  if (error instanceof Error && error.message === 'Banner not found') {\n    return; // benign: banner expired or was already dismissed\n  }\n  throw error;\n}","preventionTips":["Use banner ids taken from the current Banners collection, not cached ones","Refetch announcements after workspace/cloud syncs","Treat duplicate dismissals of the same banner as no-ops"],"tags":["uikit","cloud","announcements","banner","not-found","stale-data"],"backgroundTag":"resource-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}