RocketChat/Rocket.Chat · error · Meteor.Error

Emoji not found.

Error message

Emoji not found.

What it means

Thrown by POST emoji-custom.update when EmojiCustom.findOneById(fields._id) returns null - the multipart _id field does not match any custom-emoji document. The handler needs the existing emoji to capture previousName/previousExtension for file cleanup, so a dangling id is a hard failure.

Solutions

  1. Re-fetch the current id via GET emoji-custom.list (or emoji-custom.all) right before updating and use that _id
  2. Confirm the emoji still exists and you are pointing at the same server/user-auth-scope that listed it
  3. Trim and validate the _id string (24 hex chars for standard Mongo ObjectIds) before sending

Example fix

// before
await updateEmoji({ _id: 'myemoji' }); // name used as id -> not found

// after
const { emojis } = await sdk.get('emoji-custom.all');
const emoji = emojis.update?.[0] ?? emojis.find((e) => e.name === 'myemoji');
if (!emoji) throw new Error('emoji does not exist');
await updateEmoji({ _id: emoji._id });
Defensive patterns

Strategy: try-catch

Validate before calling

const exists = await sdk.get('emoji-custom.list', { query: JSON.stringify({ _id: emojiId }) });
if (!exists.emojis.update.length) throw new Error(`emoji ${emojiId} no longer exists`);

Try / catch

try {
  await sdk.post('emoji-custom.update', form);
} catch (e) {
  if (e.message === 'Emoji not found.') {
    const fresh = await resolveEmojiIdByName(name); // re-list and rebuild form with current _id
    if (!fresh) return; // emoji was deleted; skip
    await sdk.post('emoji-custom.update', rebuildForm(form, fresh));
  } else throw e;
}

Prevention

When it happens

Trigger: POST emoji-custom.update with an _id from a different workspace, an emoji that was already deleted, an id copied with extra whitespace/quotes, or the name of the emoji passed instead of its _id.

Common situations: Stale cached emoji lists after an admin re-imported or pruned emojis; scripts generated against a dev environment being run against production; confusing the emoji name ('myemoji') with the document _id; concurrent deletion by another admin between list and update.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/93be2ecdb3aa2d29. Report an issue: GitHub.

Appendix: source

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

		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,
			};

			const isNewFile = fileBuffer?.length && !!mimetype;
			if (isNewFile) {
				emojiData.newFile = isNewFile;
				const isUploadable = await Media.isImage(fileBuffer);
				if (!isUploadable) {
					throw new Meteor.Error('emoji-is-not-image', "Emoji file provided cannot be uploaded since it's not an image");

View on GitHub (pinned to b2c16d5842)