RocketChat/Rocket.Chat · error · Error
invalid user
Error message
invalid user
What it means
`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.
Source
Thrown at apps/meteor/server/modules/core-apps/cloudSubscriptionCommunication.module.ts:16
import type { UiKitCoreAppViewClosedPayload } from '@rocket.chat/core-services';
import type * as UiKit from '@rocket.chat/ui-kit';
import { CloudAnnouncementsModule } from './cloudAnnouncements.module';
export class CloudSubscriptionCommunication extends CloudAnnouncementsModule {
override appId = 'cloud-communication-core';
override async viewClosed(payload: UiKitCoreAppViewClosedPayload): Promise<UiKit.ServerInteraction> {
const {
payload: { view: { viewId } = {} },
user: { _id: userId } = {},
} = payload;
if (!userId) {
throw new Error('invalid user');
}
if (!viewId) {
throw new Error('invalid view');
}
if (!payload.triggerId) {
throw new Error('invalid triggerId');
}
// for viewClosed we just need to let Cloud know that the banner was closed, no need to wait for the response
void this.handlePayload(payload);
return {
type: 'modal.close',
triggerId: payload.triggerId,
appId: payload.appId,View on GitHub (pinned to b2c16d5842)
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.
Example fix
// before
await cloudCommunicationModule.viewClosed({ appId: 'cloud-communication-core', payload: { view: { viewId } }, triggerId } as any);
// after
await cloudCommunicationModule.viewClosed({ appId: 'cloud-communication-core', user: { _id: userId }, payload: { view: { viewId } }, triggerId } as any); Defensive patterns
Strategy: validation
Validate before calling
const canClose = (payload: UiKitCoreAppViewClosedPayload): boolean =>
Boolean(payload.user?._id && payload.payload?.view?.viewId && payload.triggerId);
if (canClose(payload)) {
await cloudCommunicationModule.viewClosed(payload);
} Type guard
function isCompleteCloudCommunicationClosePayload(
payload: UiKitCoreAppViewClosedPayload,
): payload is UiKitCoreAppViewClosedPayload & { user: { _id: string }; payload: { view: { viewId: string } }; triggerId: string } {
return Boolean(payload.user?._id && payload.payload?.view?.viewId && payload.triggerId);
} Try / catch
try {
await cloudCommunicationModule.viewClosed(payload);
} catch (error) {
if (error instanceof Error && error.message === 'invalid user') {
return; // no user to attribute the close to
}
throw error;
} Prevention
- Attach the acting user to every core-app interaction
- Do not reuse announcement payloads (no legacy id fallback here)
When it happens
Trigger: 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.
Common situations: Programmatic closing of cloud subscription modals; mocks omitting the user; stale surfaces after logout.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/3c122917504b2f54.
Report an issue: GitHub.