RocketChat/Rocket.Chat · error

Invalid description

Error message

Invalid description

What it means

AppModerationBridge.report throws when the description passed to the moderation report API is falsy (undefined, null, ''). Rocket.Chat requires every message report to carry a human-readable reason; unlike userId, description has no default fallback, so an empty description is rejected before reportMessage runs.

Solutions

  1. Always pass a non-empty description, even for automated reports (e.g. 'Flagged automatically by app X')
  2. Trim and check before calling: if (!description?.trim()) return
  3. Require and validate the reason field in any app UI before submitting

Example fix

// before
await app.getRocketChat().getModeration().reportMessage(messageId, reasonFromForm, userId); // blank form -> throws
// after
const description = reasonFromForm?.trim() || `Flagged by app ${app.getID()}`;
await app.getRocketChat().getModeration().reportMessage(messageId, description, userId);
Defensive patterns

Strategy: validation

Validate before calling

const description = (reasonFromForm ?? '').trim() || `Flagged automatically by app ${app.getID()}`;
await app.getRocketChat().getModeration().reportMessage(messageId, description, userId);

Type guard

const isNonEmptyDescription = (d: unknown): d is string =>
  typeof d === 'string' && d.trim().length > 0;

if (!isNonEmptyDescription(reason)) { /* prompt user or bail */ }

Try / catch

try {
  await app.getRocketChat().getModeration().reportMessage(messageId, description, userId);
} catch (err) {
  if (err instanceof Error && err.message === 'Invalid description') {
    app.getLogger().warn('report skipped: empty description');
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: An app reports a message without passing a description argument, passes an empty string, or passes a variable that resolves to undefined (optional config, empty form field).

Common situations: Apps reporting from automated hooks (e.g. onPostMessage) with no reason text wired in; UI modals where the reason textarea was left blank and the value was not validated.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/ab7d13a808907f2b. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/app/apps/server/bridges/moderation.ts:22

import type { IUser } from '@rocket.chat/apps-engine/definition/users';
import { ModerationReports } from '@rocket.chat/models';

import { reportMessage } from '../../../../server/lib/moderation/reportMessage';

export class AppModerationBridge extends ModerationBridge {
	constructor(private readonly orch: IAppServerOrchestrator) {
		super();
	}

	protected async report(messageId: IMessage['id'], description: string, userId: string, appId: string): Promise<void> {
		this.orch.debugLog(`The App ${appId} is creating a new report.`);

		if (!messageId) {
			throw new Error('Invalid message id');
		}

		if (!description) {
			throw new Error('Invalid description');
		}

		await reportMessage(messageId, description, userId || 'rocket.cat');
	}

	protected async dismissReportsByMessageId(messageId: IMessage['id'], reason: string, action: string, appId: string): Promise<void> {
		this.orch.debugLog(`The App ${appId} is dismissing reports by message id.`);

		if (!messageId) {
			throw new Error('Invalid message id');
		}

		await ModerationReports.hideMessageReportsByMessageId(messageId, appId, reason, action);
	}

	protected async dismissReportsByUserId(userId: IUser['id'], reason: string, action: string, appId: string): Promise<void> {
		this.orch.debugLog(`The App ${appId} is dismissing reports by user id.`);

View on GitHub (pinned to b2c16d5842)