RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-room
error-invalid-room
Error message
Invalid room
What it means
Thrown by addIncomingIntegration while resolving each channel target. The leading '#' or '@' is stripped (channel.substr(1)), then '#x' is looked up in Rooms by _id or name and '@x' in Users by _id or username. If no document matches, the target does not exist and 'error-invalid-room' is thrown. This is a data lookup failure, not a permission failure.
Source
Thrown at apps/meteor/server/meteor-methods/integrations/incoming/addIncomingIntegration.ts:155
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', {
method: 'addIncomingIntegration',
});
}
if (
!(await hasAllPermissionAsync(userId, ['manage-incoming-integrations', 'manage-own-incoming-integrations'])) &&
!(await Subscriptions.findOneByRoomIdAndUserId(record._id, userId, { projection: { _id: 1 } }))
) {
throw new Meteor.Error('error-invalid-channel', 'Invalid Channel', {
method: 'addIncomingIntegration',
});
}
}
const strippedIntegrationData = removeEmpty(integrationData);
const { insertedId } = await Integrations.insertOne(strippedIntegrationData);
View on GitHub (pinned to b2c16d5842)
Solutions
- Use the exact room name (lowercase slug from the room's URL, without the #) for room targets
- Create the room or user first, then create the integration
- Verify targets ahead of time from server code with Rooms.findOne({ name }) / Users.findOneByUsername or via GET /api/v1/channels.info
Example fix
// before
Meteor.callAsync('addIncomingIntegration', { ...integration, channel: '#General Chat' }); // no room named 'General Chat'
// after
await Meteor.callAsync('createChannel', 'general-chat', ['rocket.cat']); // ensure the room exists
Meteor.callAsync('addIncomingIntegration', { ...integration, channel: '#general-chat' }); Defensive patterns
Strategy: validation
Validate before calling
// server-side caller: resolve every target before creating the integration
import { Rooms, Users } from '@rocket.chat/models';
for (const entry of integration.channel.split(',')) {
const type = entry.trim()[0]; const name = entry.trim().slice(1);
const record = type === '#' ? await Rooms.findOne({ $or: [{ _id: name }, { name }] }) : await Users.findOne({ $or: [{ _id: name }, { username: name }] });
if (!record) throw new Error(`target does not exist: ${entry.trim()}`);
}
await Meteor.callAsync('addIncomingIntegration', integration); Try / catch
try {
await Meteor.callAsync('addIncomingIntegration', integration);
} catch (err) {
if (err instanceof Meteor.Error && err.error === 'error-invalid-room') { /* re-validate room list, offer room picker */ }
} Prevention
- Select channels from the room directory, never free-typed names
- Create rooms before integrations in provisioning order
- Re-check targets when re-deploying to another environment
When it happens
Trigger: '#genral' (typo); room renamed or deleted between selection and submit; '#General' where the room name is 'general' (names are lowercase, case-sensitive here); '@former.employee' whose account was deleted.
Common situations: Integration forms storing stale room lists; provisioning scripts that create integrations before creating the channels; users typing display names like 'General Chat' instead of the slug 'general-chat'.
Related errors
- error-invalid-room
- error-invalid-channel
- error-invalid-channel-start-with-chars
- error-invalid-channel
- error-invalid-channel-start-with-chars
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/a533971b42483ecb.
Report an issue: GitHub.