{"record":{"id":"e6a4cd0a4fcb427a","repo":"RocketChat/Rocket.Chat","slug":"invalid-command-usage","errorCode":"invalid-command-usage","errorMessage":"Executing a command requires at least a message with a room id.","messagePattern":"Executing a command requires at least a message with a room id\\.","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/utils/slashCommand.ts","lineNumber":76,"sourceCode":"\t\tcommand,\n\t\tmessage,\n\t\tparams,\n\t\ttriggerId,\n\t\tuserId,\n\t}: {\n\t\tcommand: string;\n\t\tparams: string;\n\t\tmessage: RequiredField<Partial<IMessage>, 'rid' | '_id'>;\n\t\tuserId: string;\n\t\ttriggerId?: string | undefined;\n\t}): Promise<unknown> {\n\t\tconst cmd = this.commands[command];\n\t\tif (typeof cmd?.callback !== 'function') {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!message?.rid) {\n\t\t\tthrow new MeteorError('invalid-command-usage', 'Executing a command requires at least a message with a room id.');\n\t\t}\n\n\t\treturn cmd.callback({ command, params, message, triggerId, userId });\n\t},\n\tasync getPreviews(\n\t\tcommand: string,\n\t\tparams: string,\n\t\tmessage: RequiredField<Partial<IMessage>, 'rid'>,\n\t\tuserId: string,\n\t): Promise<SlashCommandPreviews | undefined> {\n\t\tconst cmd = this.commands[command];\n\t\tif (typeof cmd?.previewer !== 'function') {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!message?.rid) {\n\t\t\tthrow new MeteorError('invalid-command-usage', 'Executing a command requires at least a message with a room id.');\n\t\t}","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/utils/slashCommand.ts#L58-L94","documentation":"slashCommands.run() refuses to execute a registered slash command when the message object has no rid, because every command callback needs a room context to act in. The (deprecated, use POST /v1/commands.run) Meteor method 'slashCommand' forwards the client's msg here, so an empty or partial msg surfaces as invalid-command-usage. Unknown or unregistered commands are silently ignored earlier by the callback check, so this error implies the command itself was found.","triggerScenarios":"Meteor.call('slashCommand', { cmd, params, msg }) with msg.rid undefined; server code calling slashCommands.run({ command, params, message: {} as any, userId }); command-palette UI forwarding a draft message that was never attached to a room.","commonSituations":"Bots/integrations invoking slash commands without a room; hand-built message objects that only set _id or text; refactors that dropped rid from composer state before send.","solutions":["Build the message with at least { _id, rid } before calling slashCommands.run or the DDP method.","Prefer REST POST /api/v1/commands.run with command/roomId/params, which constructs the message server-side.","In server code, pass the target room's id explicitly on every command invocation."],"exampleFix":"// before: no rid -> invalid-command-usage\nawait slashCommands.run({\n  command: 'gimme',\n  params: 'a cat picture',\n  message: { _id: Random.id() } as any,\n  userId,\n});\n\n// after\nawait slashCommands.run({\n  command: 'gimme',\n  params: 'a cat picture',\n  message: { _id: Random.id(), rid: roomId },\n  userId,\n});","handlingStrategy":"type-guard","validationCode":"if (!hasRoomId(message)) {\n  throw new Error('refusing to run slash command without a room');\n}\nawait slashCommands.run({ command, params, message, userId });","typeGuard":"const hasRoomId = (m: unknown): m is { rid: string } =>\n  typeof m === 'object' &&\n  m !== null &&\n  typeof (m as { rid?: unknown }).rid === 'string' &&\n  (m as { rid: string }).rid.length > 0;","tryCatchPattern":"try {\n  await Meteor.callAsync('slashCommand', { cmd, params, msg });\n} catch (err: any) {\n  if (err?.error === 'invalid-command-usage') {\n    // msg.rid was missing: re-attach the room id and retry once\n    return Meteor.callAsync('slashCommand', { cmd, params, msg: { ...msg, rid: currentRoomId } });\n  }\n  throw err;\n}","preventionTips":["Always build the message from the composer's room context ({ _id, rid }) before invoking slash commands.","Use POST /api/v1/commands.run (roomId is required by its schema) for integrations instead of the raw DDP method.","Treat rid as mandatory in your command-dispatch wrappers and assert it in dev builds."],"tags":["slash-commands","message","room-id","validation"],"backgroundTag":"missing-required-field","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}