RocketChat/Rocket.Chat · error · Meteor.Error
error-roomid-param-not-provided
error-roomid-param-not-provided
Error message
The parameter "roomId" is required
What it means
GET /api/v1/im.messages.others requires the roomId query parameter. The action destructures this.queryParams and throws error-roomid-param-not-provided (apps/meteor/server/api/v1/im.ts:799) when roomId is missing or an empty string. This runs after the endpoint-enabled check but before any database access, so it fails fast with no side effects.
Solutions
- Append ?roomId=<dmRoomId> where the id is a direct-message room (t === 'd')
- Fetch valid ids first via GET /api/v1/im.list and pick rooms with t: 'd'
- Check exact casing and location: query parameter roomId, not roomid, rid, or a body field
Example fix
# before curl -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $UID" \ "https://chat.example.com/api/v1/im.messages.others" # => 400 error-roomid-param-not-provided # after curl -H "X-Auth-Token: $TOKEN" -H "X-User-Id: $UID" \ "https://chat.example.com/api/v1/im.messages.others?roomId=AbCdEf123"
Defensive patterns
Strategy: validation
Validate before calling
function requireRoomId(params: Record<string, unknown>): string {
const roomId = params.roomId;
if (typeof roomId !== 'string' || roomId.trim() === '') {
throw new Error('roomId query parameter is required for im.messages.others');
}
return roomId;
}
const roomId = requireRoomId({ roomId }); // pass exactly this key Type guard
const hasRoomId = (q: Record<string, unknown>): q is { roomId: string } =>
typeof q.roomId === 'string' && q.roomId.trim().length > 0; Prevention
- Centralize query-string building so empty values fail loudly instead of being dropped
- Note the naming asymmetry: im.* GET endpoints use roomId in the query, POST siblings use rid in the body
- Assert required params before every request in integration tests
When it happens
Trigger: Calling /api/v1/im.messages.others with no query string, with roomId= (empty), or with a differently-cased key such as roomid or rid. Only exact roomId is read.
Common situations: Clients that build query strings conditionally and silently drop empty values; developers mixing conventions because other im.* POST endpoints (im.messages, im.open) take rid in the body while this GET endpoint wants roomId in the query; copy-paste from im.history examples that use a different field name.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- error-invalid-param
- error-invalid-room
- error-param-not-provided
- error-roomId-param-invalid
- error-roomid-param-not-provided
AI-assisted analysis of RocketChat/Rocket.Chat@e4b8178b20 (2026-08-18).
Data as JSON: /api/errors/d8a70f3efe558b78.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/im.ts:805
response: {
200: paginatedMessagesResponseSchema,
400: validateBadRequestErrorResponse,
401: validateUnauthorizedErrorResponse,
403: validateForbiddenErrorResponse,
},
};
const dmMessagesOthersAction = <Path extends string>(_name: Path): TypedAction<typeof dmMessagesOthersEndpointsProps, Path> =>
async function action() {
if (settings.get('API_Enable_Direct_Message_History_EndPoint') !== true) {
throw new Meteor.Error('error-endpoint-disabled', 'This endpoint is disabled', {
route: '/api/v1/im.messages.others',
});
}
const { roomId } = this.queryParams;
if (!roomId) {
throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" is required');
}
const room = await Rooms.findOneById<Pick<IRoom, '_id' | 't'>>(roomId, { projection: { _id: 1, t: 1 } });
if (!room || room?.t !== 'd') {
throw new Meteor.Error('error-room-not-found', `No direct message room found by the id of: ${roomId}`);
}
const { offset, count } = await getPaginationItems(this.queryParams);
const { sort, fields, query } = await this.parseJsonQuery();
const ourQuery = Object.assign({}, query, { rid: room._id });
const { cursor, totalCount } = Messages.findPaginated<IMessage>(ourQuery, {
sort: sort || { ts: -1 },
skip: offset,
limit: count,
projection: fields,
});
View on GitHub (pinned to e4b8178b20)