{"record":{"id":"d8a70f3efe558b78","repo":"RocketChat/Rocket.Chat","slug":"error-roomid-param-not-provided-d8a70f","errorCode":"error-roomid-param-not-provided","errorMessage":"The parameter \"roomId\" is required","messagePattern":"The parameter \"roomId\" is required","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/im.ts","lineNumber":805,"sourceCode":"\tresponse: {\n\t\t200: paginatedMessagesResponseSchema,\n\t\t400: validateBadRequestErrorResponse,\n\t\t401: validateUnauthorizedErrorResponse,\n\t\t403: validateForbiddenErrorResponse,\n\t},\n};\n\nconst dmMessagesOthersAction = <Path extends string>(_name: Path): TypedAction<typeof dmMessagesOthersEndpointsProps, Path> =>\n\tasync function action() {\n\t\tif (settings.get('API_Enable_Direct_Message_History_EndPoint') !== true) {\n\t\t\tthrow new Meteor.Error('error-endpoint-disabled', 'This endpoint is disabled', {\n\t\t\t\troute: '/api/v1/im.messages.others',\n\t\t\t});\n\t\t}\n\n\t\tconst { roomId } = this.queryParams;\n\t\tif (!roomId) {\n\t\t\tthrow new Meteor.Error('error-roomid-param-not-provided', 'The parameter \"roomId\" is required');\n\t\t}\n\n\t\tconst room = await Rooms.findOneById<Pick<IRoom, '_id' | 't'>>(roomId, { projection: { _id: 1, t: 1 } });\n\t\tif (!room || room?.t !== 'd') {\n\t\t\tthrow new Meteor.Error('error-room-not-found', `No direct message room found by the id of: ${roomId}`);\n\t\t}\n\n\t\tconst { offset, count } = await getPaginationItems(this.queryParams);\n\t\tconst { sort, fields, query } = await this.parseJsonQuery();\n\t\tconst ourQuery = Object.assign({}, query, { rid: room._id });\n\n\t\tconst { cursor, totalCount } = Messages.findPaginated<IMessage>(ourQuery, {\n\t\t\tsort: sort || { ts: -1 },\n\t\t\tskip: offset,\n\t\t\tlimit: count,\n\t\t\tprojection: fields,\n\t\t});\n","sourceCodeStart":787,"sourceCodeEnd":823,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/e4b8178b205510181a96ceefee043d0abcd13e5a/apps/meteor/server/api/v1/im.ts#L787-L823","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\n curl -H \"X-Auth-Token: $TOKEN\" -H \"X-User-Id: $UID\" \\\n  \"https://chat.example.com/api/v1/im.messages.others\"\n # => 400 error-roomid-param-not-provided\n\n # after\n curl -H \"X-Auth-Token: $TOKEN\" -H \"X-User-Id: $UID\" \\\n  \"https://chat.example.com/api/v1/im.messages.others?roomId=AbCdEf123\"","handlingStrategy":"validation","validationCode":"function requireRoomId(params: Record<string, unknown>): string {\n  const roomId = params.roomId;\n  if (typeof roomId !== 'string' || roomId.trim() === '') {\n    throw new Error('roomId query parameter is required for im.messages.others');\n  }\n  return roomId;\n}\nconst roomId = requireRoomId({ roomId }); // pass exactly this key","typeGuard":"const hasRoomId = (q: Record<string, unknown>): q is { roomId: string } =>\n  typeof q.roomId === 'string' && q.roomId.trim().length > 0;","tryCatchPattern":null,"preventionTips":["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"],"tags":["rest-api","validation","query-params","direct-message"],"backgroundTag":"missing-required-argument","analyzedSha":"e4b8178b205510181a96ceefee043d0abcd13e5a","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}