{"record":{"id":"9e9bbdc4d0066c95","repo":"RocketChat/Rocket.Chat","slug":"app-already-exists","errorCode":null,"errorMessage":"App already exists.","messagePattern":"App already exists\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/ee/server/apps/storage/AppRealStorage.ts","lineNumber":23,"sourceCode":"import type { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';\nimport type { ISetting } from '@rocket.chat/apps-engine/definition/settings';\nimport type { Apps } from '@rocket.chat/models';\nimport { removeEmpty } from '@rocket.chat/tools';\nimport type { UpdateFilter } from 'mongodb';\n\nexport class AppRealStorage extends AppMetadataStorage {\n\tconstructor(private db: typeof Apps) {\n\t\tsuper('mongodb');\n\t}\n\n\tpublic async create(item: IAppStorageItem): Promise<IAppStorageItem> {\n\t\titem.createdAt = new Date();\n\t\titem.updatedAt = new Date();\n\n\t\tconst doc = await this.db.findOne({ $or: [{ id: item.id }, { 'info.nameSlug': item.info.nameSlug }] });\n\n\t\tif (doc) {\n\t\t\tthrow new Error('App already exists.');\n\t\t}\n\n\t\tconst nonEmptyItem = removeEmpty(item);\n\t\tconst id = (await this.db.insertOne(nonEmptyItem)).insertedId as unknown as string;\n\t\tnonEmptyItem._id = id;\n\n\t\treturn nonEmptyItem;\n\t}\n\n\tpublic async retrieveOne(id: string): Promise<IAppStorageItem> {\n\t\treturn this.db.findOne({ $or: [{ _id: id }, { id }] });\n\t}\n\n\tpublic async retrieveAll(): Promise<Map<string, IAppStorageItem>> {\n\t\tconst docs = await this.db.find({}).toArray();\n\t\tconst items = new Map();\n\n\t\tdocs.forEach((i) => items.set(i.id, i));","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/ee/server/apps/storage/AppRealStorage.ts#L5-L41","documentation":"Thrown by `AppRealStorage.create()` when a document already exists matching the new app's `id` OR its `info.nameSlug`. The storage enforces uniqueness on both the app ID and the human-readable name slug to prevent duplicate marketplace/installed apps. It is a plain `Error`, not a typed/Meteor error.","triggerScenarios":"Calling `create(item)` where `this.db.findOne({ $or: [{ id: item.id }, { 'info.nameSlug': item.info.nameSlug }] })` returns a non-null document.","commonSituations":"Re-installing an app that is already in the DB (possibly in a removed/disabled state); two apps sharing the same nameSlug due to a packaging mistake; a retry of an install that partially succeeded.","solutions":["Check whether the app already exists (by id or nameSlug) before calling `create()`; if it does, call `update()` instead.","Remove the existing app record first if a clean re-install is intended.","Ensure app packages have unique nameSlugs when publishing to avoid collisions."],"exampleFix":"// before\nawait Apps.create(item); // throws if duplicate\n\n// after\nconst existing = await Apps.findOne({ $or: [{ id: item.id }, { 'info.nameSlug': item.info.nameSlug }] });\nif (existing) {\n\tawait Apps.update(item);\n} else {\n\tawait Apps.create(item);\n}","handlingStrategy":"validation","validationCode":"async function appExists(id: string, nameSlug: string): Promise<boolean> {\n\tconst doc = await Apps.findOne({ $or: [{ id }, { 'info.nameSlug': nameSlug }] });\n\treturn Boolean(doc);\n}","typeGuard":"function isAppAlreadyExistsError(e: unknown): boolean {\n\treturn e instanceof Error && e.message === 'App already exists.';\n}","tryCatchPattern":"try {\n\tawait Apps.create(item);\n} catch (e) {\n\tif (e instanceof Error && e.message === 'App already exists.') {\n\t\tawait Apps.update(item); // or skip\n\t\treturn;\n\t}\n\tthrow e;\n}","preventionTips":["Check for an existing record by id/nameSlug before calling `create()`.","Use `update()` for re-installs instead of `create()`.","Ensure published apps have unique nameSlugs."],"tags":["apps-engine","storage","duplicate","ee"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}