{"record":{"id":"1e96f4d6277b2ec6","repo":"RocketChat/Rocket.Chat","slug":"the-required-id-query-param-is-missing","errorCode":null,"errorMessage":"The required \"_id\" query param is missing.","messagePattern":"The required \"_id\" query param is missing\\.","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/emoji-custom.ts","lineNumber":247,"sourceCode":"\t\t\t\t\trequired: ['success'],\n\t\t\t\t\tadditionalProperties: false,\n\t\t\t\t}),\n\t\t\t\t400: validateBadRequestErrorResponse,\n\t\t\t\t401: validateUnauthorizedErrorResponse,\n\t\t\t},\n\t\t},\n\t\tasync function action() {\n\t\t\tconst emoji = await getUploadFormData(\n\t\t\t\t{\n\t\t\t\t\trequest: this.request,\n\t\t\t\t},\n\t\t\t\t{ field: 'emoji', sizeLimit: settings.get('FileUpload_MaxFileSize'), fileOptional: true },\n\t\t\t);\n\n\t\t\tconst { fields, fileBuffer, mimetype } = emoji;\n\n\t\t\tif (!fields._id) {\n\t\t\t\tthrow new Meteor.Error('The required \"_id\" query param is missing.');\n\t\t\t}\n\n\t\t\tconst emojiToUpdate = await EmojiCustom.findOneById<Pick<IEmojiCustom, 'name' | 'extension'>>(fields._id, {\n\t\t\t\tprojection: { name: 1, extension: 1 },\n\t\t\t});\n\t\t\tif (!emojiToUpdate) {\n\t\t\t\tthrow new Meteor.Error('Emoji not found.');\n\t\t\t}\n\n\t\t\tconst emojiData: EmojiData = {\n\t\t\t\tpreviousName: emojiToUpdate.name,\n\t\t\t\tpreviousExtension: emojiToUpdate.extension,\n\t\t\t\taliases: fields.aliases || '',\n\t\t\t\tname: fields.name,\n\t\t\t\textension: fields.extension,\n\t\t\t\t_id: fields._id,\n\t\t\t\tnewFile: false,\n\t\t\t};","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/v1/emoji-custom.ts#L229-L265","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","solutions":["Add a plain text multipart form field named exactly _id carrying the emoji document id: form.append('_id', emojiId)","Get the correct id first from GET emoji-custom.list / emoji-custom.all (the _id property of each emoji)","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"],"exampleFix":"// before\nconst form = new FormData();\nform.append('name', 'new-name');\nform.append('emoji', file); // _id never sent\n\n// after\nconst form = new FormData();\nform.append('_id', emojiId);\nform.append('name', 'new-name');\nform.append('emoji', file);","handlingStrategy":"validation","validationCode":"function buildEmojiUpdateForm(emojiId, fields, file) {\n  if (!emojiId) throw new Error('emoji-custom.update requires the emoji _id');\n  const form = new FormData();\n  form.append('_id', emojiId);\n  for (const [k, v] of Object.entries(fields)) form.append(k, v);\n  if (file) form.append('emoji', file);\n  return form;\n}","typeGuard":"const hasEmojiId = (body: Record<string, unknown>): body is { _id: string } & Record<string, unknown> =>\n  typeof body._id === 'string' && body._id.length > 0;","tryCatchPattern":"try { await sdk.post('emoji-custom.update', form); } catch (e) {\n  if (String(e.message).includes('\"_id\" query param is missing')) { /* attach _id field and retry once */ }\n}","preventionTips":["Remember emoji-custom.update is multipart/form-data; _id is a form field, not a URL/JSON param","Write one form-builder function so every call site gets _id handling right","Fetch the _id from emoji-custom.list immediately before updating to avoid stale ids"],"tags":["rest-api","emoji-custom","multipart-formdata","required-parameter"],"backgroundTag":"missing-required-argument","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}