RocketChat/Rocket.Chat · error · Meteor.Error

The required "_id" query param is missing.

Error message

The required "_id" query param is missing.

What it means

Thrown by POST emoji-custom.update when the multipart form data contains no _id field. The endpoint reads everything through getUploadFormData and expects the emoji's document id as a form field named _id; unlike most REST endpoints it is not taken from the URL query or a JSON body. Note the error is constructed with a single argument, so the message doubles as the error identifier in the response.

Solutions

  1. Add a plain text multipart form field named exactly _id carrying the emoji document id: form.append('_id', emojiId)
  2. Get the correct id first from GET emoji-custom.list / emoji-custom.all (the _id property of each emoji)
  3. Keep sending the rest of the payload as multipart/form-data with the optional 'emoji' file field - do not switch the request to application/json

Example fix

// before
const form = new FormData();
form.append('name', 'new-name');
form.append('emoji', file); // _id never sent

// after
const form = new FormData();
form.append('_id', emojiId);
form.append('name', 'new-name');
form.append('emoji', file);
Defensive patterns

Strategy: validation

Validate before calling

function buildEmojiUpdateForm(emojiId, fields, file) {
  if (!emojiId) throw new Error('emoji-custom.update requires the emoji _id');
  const form = new FormData();
  form.append('_id', emojiId);
  for (const [k, v] of Object.entries(fields)) form.append(k, v);
  if (file) form.append('emoji', file);
  return form;
}

Type guard

const hasEmojiId = (body: Record<string, unknown>): body is { _id: string } & Record<string, unknown> =>
  typeof body._id === 'string' && body._id.length > 0;

Try / catch

try { await sdk.post('emoji-custom.update', form); } catch (e) {
  if (String(e.message).includes('"_id" query param is missing')) { /* attach _id field and retry once */ }
}

Prevention

When it happens

Trigger: POST /api/v1/emoji-custom.update with multipart fields name/aliases/emoji but no _id field; sending _id as a query parameter (?_id=abc) or inside a JSON body - the handler never sees it because it only reads getUploadFormData fields; a typo like 'id' or 'emojiId' instead of '_id'.

Common situations: Developers assuming REST conventions where the id goes in the URL or query string; clients switching from emoji-custom.delete (which uses emojiId in a JSON body) to update and reusing the field name; multipart builders that drop fields with underscore-prefixed names.

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


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/1e96f4d6277b2ec6. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/server/api/v1/emoji-custom.ts:247

					required: ['success'],
					additionalProperties: false,
				}),
				400: validateBadRequestErrorResponse,
				401: validateUnauthorizedErrorResponse,
			},
		},
		async function action() {
			const emoji = await getUploadFormData(
				{
					request: this.request,
				},
				{ field: 'emoji', sizeLimit: settings.get('FileUpload_MaxFileSize'), fileOptional: true },
			);

			const { fields, fileBuffer, mimetype } = emoji;

			if (!fields._id) {
				throw new Meteor.Error('The required "_id" query param is missing.');
			}

			const emojiToUpdate = await EmojiCustom.findOneById<Pick<IEmojiCustom, 'name' | 'extension'>>(fields._id, {
				projection: { name: 1, extension: 1 },
			});
			if (!emojiToUpdate) {
				throw new Meteor.Error('Emoji not found.');
			}

			const emojiData: EmojiData = {
				previousName: emojiToUpdate.name,
				previousExtension: emojiToUpdate.extension,
				aliases: fields.aliases || '',
				name: fields.name,
				extension: fields.extension,
				_id: fields._id,
				newFile: false,
			};

View on GitHub (pinned to b2c16d5842)