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
- Re-fetch the current id via GET emoji-custom.list (or emoji-custom.all) right before updating and use that _id
- Confirm the emoji still exists and you are pointing at the same server/user-auth-scope that listed it
- 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
- Treat emoji ids as ephemeral: resolve name -> _id via emoji-custom.list in the same run
- In long-lived automation, refresh the emoji map on a schedule or on every not-found
- Log the _id you sent so mismatches with the server are diagnosable
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
- emoji-is-not-image
- error-challenge-not-found
- error-invalid-roleId
- error-invalid-subscription
- error-invalid-user
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)