RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-room

error-invalid-room

Error message

Invalid room

What it means

Thrown by _verifyUserHasPermissionForChannels when a channel entry starts with '#' or '@' but no matching record exists: '#' entries are looked up in Rooms by _id or name, '@' entries in Users by _id or username. A miss means the referenced room or user does not exist (or is not visible), and validation stops with Meteor.Error code 'error-invalid-room'.

Source

Thrown at apps/meteor/server/lib/integrations/lib/validateOutgoingIntegration.ts:83

			let record;
			const channelType = channel[0];
			channel = channel.substr(1);

			switch (channelType) {
				case '#':
					record = await Rooms.findOne({
						$or: [{ _id: channel }, { name: channel }],
					});
					break;
				case '@':
					record = await Users.findOne({
						$or: [{ _id: channel }, { username: channel }],
					});
					break;
			}

			if (!record) {
				throw new Meteor.Error('error-invalid-room', 'Invalid room', {
					function: 'validateOutgoing._verifyUserHasPermissionForChannels',
				});
			}

			if (
				!(await hasAllPermissionAsync(userId, ['manage-outgoing-integrations', 'manage-own-outgoing-integrations'])) &&
				!(await Subscriptions.findOneByRoomIdAndUserId(record._id, userId, { projection: { _id: 1 } }))
			) {
				throw new Meteor.Error('error-invalid-channel', 'Invalid Channel', {
					function: 'validateOutgoing._verifyUserHasPermissionForChannels',
				});
			}
		}
	}
}

function _verifyRetryInformation(integration: IOutgoingIntegration): void {
	if (!integration.retryFailedCalls) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Correct the channel name/username after the '#'/'@' prefix and re-submit
  2. Trim each CSV entry before submitting to avoid invisible whitespace mismatches
  3. Verify existence first: GET /api/v1/channels.info?roomName=... or users.info?username=... for each target

Example fix

// before
{ channel: '#genral' } // typo

// after
{ channel: '#general' }
Defensive patterns

Strategy: validation

Validate before calling

const name = channel.slice(1).trim();
const record = channel.startsWith('#')
  ? await Rooms.findOne({ $or: [{ _id: name }, { name }] })
  : await Users.findOne({ $or: [{ _id: name }, { username: name }] });
if (!record) {
  throw new Error(`channel ${channel} does not exist`);
}

Prevention

When it happens

Trigger: integrations.create/update with channel '#genral' (typo), '#general ' (trailing space), '@former.employee' (deleted user), or a room name that was renamed after the integration form was loaded; also '#' followed by a room _id that does not exist.

Common situations: Channel renamed or archived between loading the form and saving; DM target user deleted; copy-pasting display names that differ from the real username (e.g. 'Jane Doe' vs 'jane.doe'); trailing whitespace from CSV splitting.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/1a877c0166c8159f. Report an issue: GitHub.