{"record":{"id":"ef2649a224b40e75","repo":"RocketChat/Rocket.Chat","slug":"app-could-not-be-enabled","errorCode":null,"errorMessage":"App could not be enabled","messagePattern":"App could not be enabled","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/meteor/ee/server/apps/orchestrator.ts","lineNumber":251,"sourceCode":"\t\t// Don't try to load it again if it has\n\t\t// already been loaded\n\t\tif (this.isLoaded()) {\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.getManager().load();\n\n\t\t// Before enabling each app we verify if there is still room for it\n\t\tconst apps = await this.getManager().get();\n\n\t\t// This needs to happen sequentially to keep track of app limits\n\t\tfor (const app of apps) {\n\t\t\ttry {\n\t\t\t\tawait canEnableApp(app.getStorageItem());\n\n\t\t\t\tawait this.getManager().loadOne(app.getID(), true);\n\t\t\t} catch (error) {\n\t\t\t\tthis._rocketchatLogger.warn({\n\t\t\t\t\tmsg: 'App could not be enabled',\n\t\t\t\t\tappName: app.getInfo().name,\n\t\t\t\t\terr: error,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tawait this._bridges.getSchedulerBridge().startScheduler();\n\n\t\tconst appCount = (await this.getManager().get({ enabled: true })).length;\n\n\t\tthis._rocketchatLogger.info({\n\t\t\tmsg: 'Loaded the Apps Framework and apps',\n\t\t\tappCount,\n\t\t});\n\t}\n\n\tasync migratePrivateApps(): Promise<void> {","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/ee/server/apps/orchestrator.ts#L233-L269","documentation":"Logged by the Enterprise Apps orchestrator during startup when enabling an installed app fails. Each app first passes canEnableApp() (a license gate in ee/server/lib/license/canEnableApp.ts that rejects with 'apps-engine-not-initialized', 'app-addon-not-valid', 'license-prevented', or 'invalid-license') and then manager.loadOne(id, true). The per-app try/catch keeps one failing app from blocking the rest, so only that app stays disabled; the real reason is in the log entry's err field.","triggerScenarios":"Startup enable loop hitting: (1) License.shouldPreventAction('privateApps'|'marketplaceApps') true — more apps installed than the license entitlement allows (private vs marketplace apps are counted separately); (2) an app whose info.addon module is not in the license ('app-addon-not-valid'); (3) a marketplace app flagged isEnterpriseOnly with no valid license ('invalid-license'); (4) loadOne throwing because the app package is incompatible with the installed apps-engine version or throws during its own initialization.","commonSituations":"Workspace downgraded/expired its Enterprise license while more apps than entitled remain installed; installing enterprise-only marketplace apps on a community license; apps built for a newer apps-engine after a server downgrade; Apps engine not fully initialized when the orchestrator ran.","solutions":["Read the err field of the log entry — 'license-prevented' means app-count entitlement was exceeded, 'invalid-license'/'app-addon-not-valid' mean licensing, anything else is a load failure","For license errors: uninstall or disable apps until under the entitled private/marketplace app limits, or apply a license that covers them","For load errors: update or remove the app whose appName appears in the log; check its compatibility with the server's apps-engine version","Restart the server — the orchestrator retries enabling all apps on every start"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import { License } from '@rocket.chat/license';\n\n// before enabling, confirm the entitlement path that canEnableApp checks\nasync function canSafelyEnableApp(app: { migrated?: boolean; info: { addon?: string } }): Promise<boolean> {\n\tif (app.migrated) return true;\n\tif (app.info.addon && !(await License.hasModule(app.info.addon as never))) return false;\n\treturn !(await License.shouldPreventAction('marketplaceApps'));\n}","typeGuard":null,"tryCatchPattern":"for (const app of apps) {\n\ttry {\n\t\tawait canEnableApp(app.getStorageItem());\n\t\tawait manager.loadOne(app.getID(), true);\n\t} catch (error) {\n\t\t// log with the app id AND the error; keep other apps enabling\n\t\tlogger.warn({ msg: 'App could not be enabled', appId: app.getID(), err: error });\n\t}\n}","preventionTips":["Keep enabled app counts within the license's private-apps and marketplace-apps limits before upgrading or downgrading licenses","Check an app's minimum apps-engine version before installing it","Remove broken/leftover app records after failed uninstalls so startup does not retry them forever"],"tags":["apps-engine","licensing","startup","enterprise"],"backgroundTag":"license-limit-exceeded","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}