RocketChat/Rocket.Chat · error
Only channels, private groups and direct messages can be…
Error message
Only channels, private groups and direct messages can be created.
What it means
AppRoomBridge.create only handles three apps-engine room types — RoomType.CHANNEL ('c'), RoomType.PRIVATE_GROUP ('p') and RoomType.DIRECT_MESSAGE ('d'); every other room.type hits the default branch and throws. Notably Team ('t') and Livechat ('l') rooms cannot be created through this bridge.
Solutions
- Restrict creation to CHANNEL, PRIVATE_GROUP and DIRECT_MESSAGE
- Create teams/omnichannel rooms through their dedicated server/REST APIs instead of the room bridge
- Set room.type explicitly from the RoomType enum — never from unvalidated strings
- Validate room.type before calling create and fail with your own descriptive error
Example fix
// before
const room = { type: 't' as any, ... }; // team room -> default branch throws
await app.getRocketChat().getChat().createRoom(room, members);
// after
const room = { type: RoomType.CHANNEL, creator, name: 'my-channel' };
await app.getRocketChat().getChat().createRoom(room, members); Defensive patterns
Strategy: type-guard
Validate before calling
const CREATABLE = new Set([RoomType.CHANNEL, RoomType.PRIVATE_GROUP, RoomType.DIRECT_MESSAGE]);
if (!CREATABLE.has(room.type)) {
throw new Error(`room type '${room.type}' cannot be created via the apps API`);
}
await app.getRocketChat().getChat().createRoom(room, members); Type guard
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';
const isCreatableRoomType = (t: unknown): t is RoomType.CHANNEL | RoomType.PRIVATE_GROUP | RoomType.DIRECT_MESSAGE =>
t === RoomType.CHANNEL || t === RoomType.PRIVATE_GROUP || t === RoomType.DIRECT_MESSAGE;
if (!isCreatableRoomType(room.type)) return; Try / catch
try {
await app.getRocketChat().getChat().createRoom(room, members);
} catch (err) {
if (err instanceof Error && err.message.includes('Only channels, private groups and direct messages')) {
app.getLogger().error(`room type ${room.type} is not creatable via apps`);
return;
}
throw err;
} Prevention
- Set room.type only from the RoomType enum — never from strings or copied fetched rooms
- Create teams/omnichannel rooms via their dedicated APIs, not this bridge
- Whitelist creatable types at the edge of your app code
- Test creation for each type you support
When it happens
Trigger: Creating a room with room.type = RoomType.TEAMS or RoomType.LIVECHAT (or any custom/raw string); copying the type of a fetched livechat or team room into a new IRoom passed to the create API.
Common situations: Apps trying to provision teams or omnichannel rooms via the apps API; building IRoom objects by hand with a wrong type value; assuming every value of the apps-engine RoomType enum is creatable.
Related errors
- Invalid user
- error-app-prevented
- error-app-prevented
- error-app-prevented-deleting
- error-invalid-custom-field-value
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/d5d630164b1e779f.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/app/apps/server/bridges/rooms.ts:75
export class AppRoomBridge extends RoomBridge {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
}
protected async create(room: IRoom, members: Array<string>, appId: string): Promise<string> {
this.orch.debugLog(`The App ${appId} is creating a new room.`, room);
const rcRoom = await this.orch.getConverters()?.get('rooms').convertAppRoom(room);
switch (room.type) {
case RoomType.CHANNEL:
return this.createChannel(room.creator.id, rcRoom, members);
case RoomType.PRIVATE_GROUP:
return this.createPrivateGroup(room.creator.id, rcRoom, members);
case RoomType.DIRECT_MESSAGE:
return this.createDirectMessage(room.creator.id, members);
default:
throw new Error('Only channels, private groups and direct messages can be created.');
}
}
private prepareExtraData(room: Record<string, any>): Record<string, unknown> {
const extraData = Object.assign({}, room);
delete extraData.name;
delete extraData.t;
delete extraData.ro;
delete extraData.customFields;
return extraData;
}
private async createChannel(userId: string, room: ICoreRoom, members: string[]): Promise<string> {
return (await createChannelMethod(userId, room.name || '', members, room.ro, room.customFields, this.prepareExtraData(room))).rid;
}
private async createDirectMessage(userId: string, members: string[]): Promise<string> {View on GitHub (pinned to b2c16d5842)