RocketChat/Rocket.Chat · error · Error

Invalid description

Error message

Invalid description

What it means

Thrown by AppModerationBridge.report when description is falsy. The bridge enforces a non-empty human description before forwarding to reportMessage, which itself rejects whitespace-only descriptions with 'error-invalid-description'. This guard is the cheap presence check.

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 f9d3ec372b)

Solutions

  1. Collect a non-empty reason from the user before calling report and validate it client-side in the App's UIKit handler.
  2. Provide a sensible default description when the user submits none, e.g. `description = description || 'Reported via app';` — but note reportMessage will still reject pure whitespace, so trim and check length.
  3. Skip the report call entirely if the description is empty rather than letting the bridge throw.

Example fix

// before
await moderation.report(messageId, '', userId, appId);

// after
const reason = (description || '').trim() || 'No reason provided';
await moderation.report(messageId, reason, userId, appId);
Defensive patterns

Strategy: validation

Validate before calling

const reason = (typeof description === 'string' ? description : '').trim();
if (reason.length === 0) {
  throw new Error('A non-empty description is required to report');
}
await moderation.report(messageId, reason, userId, appId);

Type guard

function isNonEmptyDescription(value: unknown): value is string {
  return typeof value === 'string' && value.trim().length > 0;
}

Prevention

When it happens

Trigger: An App calls report with description undefined, null or '' — e.g. reporting from a one-tap 'report' button that sends no reason text, or passing a description variable that was never assigned from the UI payload.

Common situations: UX flows that allow reporting without collecting a reason; forgotten required field in a modal handler; description built from an optional form field that defaulted to undefined.

Related errors


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