{"record":{"id":"3c122917504b2f54","repo":"RocketChat/Rocket.Chat","slug":"invalid-user-3c1229","errorCode":null,"errorMessage":"invalid user","messagePattern":"invalid user","errorType":"exception","errorClass":"Error","httpStatus":500,"severity":"error","filePath":"apps/meteor/server/modules/core-apps/cloudSubscriptionCommunication.module.ts","lineNumber":16,"sourceCode":"import type { UiKitCoreAppViewClosedPayload } from '@rocket.chat/core-services';\nimport type * as UiKit from '@rocket.chat/ui-kit';\n\nimport { CloudAnnouncementsModule } from './cloudAnnouncements.module';\n\nexport class CloudSubscriptionCommunication extends CloudAnnouncementsModule {\n\toverride appId = 'cloud-communication-core';\n\n\toverride async viewClosed(payload: UiKitCoreAppViewClosedPayload): Promise<UiKit.ServerInteraction> {\n\t\tconst {\n\t\t\tpayload: { view: { viewId } = {} },\n\t\t\tuser: { _id: userId } = {},\n\t\t} = payload;\n\n\t\tif (!userId) {\n\t\t\tthrow new Error('invalid user');\n\t\t}\n\n\t\tif (!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 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: 'modal.close',\n\t\t\ttriggerId: payload.triggerId,\n\t\t\tappId: payload.appId,","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/modules/core-apps/cloudSubscriptionCommunication.module.ts#L1-L34","documentation":"`CloudSubscriptionCommunication` (appId `cloud-communication-core`, extends `CloudAnnouncementsModule`) handles cloud subscription/communication modals. Its `viewClosed()` override requires `payload.user._id` to attribute the close; when missing it throws a plain `Error('invalid user')` before notifying Cloud.","triggerScenarios":"A `viewClosed` interaction for `cloud-communication-core` where `payload.user` or `payload.user._id` is undefined — synthetic payloads, test doubles, or a session that lost its user context.","commonSituations":"Programmatic closing of cloud subscription modals; mocks omitting the user; stale surfaces after logout.","solutions":["Include `user: { _id: userId }` in the viewClosed payload.","If acting server-side, avoid the module and dismiss via `Banner.dismiss` or the appropriate service directly.","Ensure the dispatcher always attaches the acting user to core-app interactions."],"exampleFix":"// before\nawait cloudCommunicationModule.viewClosed({ appId: 'cloud-communication-core', payload: { view: { viewId } }, triggerId } as any);\n\n// after\nawait cloudCommunicationModule.viewClosed({ appId: 'cloud-communication-core', user: { _id: userId }, payload: { view: { viewId } }, triggerId } as any);","handlingStrategy":"validation","validationCode":"const canClose = (payload: UiKitCoreAppViewClosedPayload): boolean =>\n  Boolean(payload.user?._id && payload.payload?.view?.viewId && payload.triggerId);\n\nif (canClose(payload)) {\n  await cloudCommunicationModule.viewClosed(payload);\n}","typeGuard":"function isCompleteCloudCommunicationClosePayload(\n  payload: UiKitCoreAppViewClosedPayload,\n): payload is UiKitCoreAppViewClosedPayload & { user: { _id: string }; payload: { view: { viewId: string } }; triggerId: string } {\n  return Boolean(payload.user?._id && payload.payload?.view?.viewId && payload.triggerId);\n}","tryCatchPattern":"try {\n  await cloudCommunicationModule.viewClosed(payload);\n} catch (error) {\n  if (error instanceof Error && error.message === 'invalid user') {\n    return; // no user to attribute the close to\n  }\n  throw error;\n}","preventionTips":["Attach the acting user to every core-app interaction","Do not reuse announcement payloads (no legacy id fallback here)"],"tags":["uikit","cloud","subscription","payload-validation","core-apps"],"backgroundTag":"uikit-interaction-payload-invalid","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"}