RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-room
error-invalid-room
Error message
Invalid room
What it means
dmBlockUserAction resolves the DM, then computes blocked = room.uids?.find(uid => uid !== this.userId). If there is no 'other' user it throws error-invalid-room with method 'im.blockUser'. This fires for self-DMs (only one uid), DMs whose uids array is empty/missing, or odd DM states.
Source
Thrown at apps/meteor/server/api/v1/im.ts:985
200: ajv.compile<void>({
type: 'object',
properties: {
success: { type: 'boolean', enum: [true] },
},
required: ['success'],
additionalProperties: false,
}),
},
} as const;
const dmBlockUserAction = <Path extends string>(_path: Path): TypedAction<typeof dmBlockUserEndpointsProps, Path> =>
async function action() {
const { roomId, block } = this.bodyParams;
const { room } = await findDirectMessageRoom({ roomId }, this.userId);
const blocked = room.uids?.find((uid) => uid !== this.userId);
if (!blocked) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'im.blockUser' });
}
if (block) {
await blockUserMethod(this.userId, { rid: room._id, blocked });
} else {
await unblockUserMethod(this.userId, { rid: room._id, blocked });
}
return API.v1.success();
};
const dmEndpoints = API.v1
.post('im.delete', dmDeleteEndpointsProps, dmDeleteAction('im.delete'))
.post('dm.delete', dmDeleteEndpointsProps, dmDeleteAction('dm.delete'))
.post('dm.close', dmCloseEndpointsProps, dmCloseAction('dm.close'))
.post('im.close', dmCloseEndpointsProps, dmCloseAction('im.close'))
.post('dm.create', dmCreateEndpointsProps, dmCreateAction('dm.create'))
.post('im.create', dmCreateEndpointsProps, dmCreateAction('im.create'))View on GitHub (pinned to f9d3ec372b)
Solutions
- Confirm the DM actually has a second participant before calling block.
- Do not call block on a self-DM.
- If the counterpart was removed, re-create the DM (im.create) before blocking.
Example fix
// before
POST /api/v1/im.blockUser { roomId: <self-dm> } // only one uid
// after
const room = await GET /api/v1/im.rooms.info?roomId=<rid>;
if (room.uids.length === 2) {
await POST /api/v1/im.blockUser { roomId, block: true };
} Defensive patterns
Strategy: validation
Validate before calling
// Verify the DM has a counterpart user before blocking
const room = (await api.get('/api/v1/rooms.info', { params: { roomId } })).data.room;
const others = (room.uids || []).filter(uid => uid !== CURRENT_USER_ID);
if (others.length !== 1) {
throw new Error('DM has no blockable counterpart user');
} Type guard
function isBlockableDm(room: unknown, me: string): room is { _id: string; uids: [string, string] } {
const uids = (room as any)?.uids;
return Array.isArray(uids) && uids.filter((u: string) => u !== me).length === 1;
} Try / catch
try {
await api.post('/api/v1/im.blockUser', { roomId, block: true });
} catch (e) {
if (e.response?.data?.error === 'error-invalid-room') {
// self-DM or no counterpart — skip blocking
} else throw e;
} Prevention
- Never call block on a self-DM.
- Check room.uids has exactly one non-caller uid first.
- Re-create DMs whose counterpart user was deleted before blocking.
When it happens
Trigger: POST /api/v1/im.blockUser on a DM that has no counterpart user — e.g. a self-message room, a DM whose other participant was removed leaving a single uid, or a malformed room document without uids.
Common situations: Trying to block yourself (the DM with yourself); the other user was deleted and the room collapsed to one uid; legacy room documents missing the uids field.
Related errors
- error-room-not-found
- error-roomid-param-not-provided
- Invalid Api parameter provided, it must be a valid IApi obje
- error-emoji-param-not-provided
- error-param-required
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/ac30af424b0dd9f8.
Report an issue: GitHub.