{"record":{"id":"0498c3d5ed2e43c4","repo":"RocketChat/Rocket.Chat","slug":"apps-engine-not-initialized","errorCode":"apps-engine-not-initialized","errorMessage":"apps-engine-not-initialized","messagePattern":"apps-engine-not-initialized","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/ee/server/lib/license/canEnableApp.ts","lineNumber":15,"sourceCode":"import type { IAppStorageItem } from '@rocket.chat/apps/dist/server/storage/IAppStorageItem';\nimport { Apps } from '@rocket.chat/core-services';\nimport type { LicenseModule } from '@rocket.chat/core-typings';\nimport { License, type LicenseImp } from '@rocket.chat/license';\n\nimport { getInstallationSourceFromAppStorageItem } from '../../../../lib/apps/getInstallationSourceFromAppStorageItem';\n\ntype _canEnableAppDependencies = {\n\tApps: typeof Apps;\n\tLicense: LicenseImp;\n};\n\nexport const _canEnableApp = async ({ Apps, License }: _canEnableAppDependencies, app: IAppStorageItem): Promise<void> => {\n\tif (!(await Apps.isInitialized())) {\n\t\tthrow new Error('apps-engine-not-initialized');\n\t}\n\n\t// Migrated apps were installed before the validation was implemented\n\t// so they're always allowed to be enabled\n\tif (app.migrated) {\n\t\treturn;\n\t}\n\n\tif (app.info.addon && !License.hasModule(app.info.addon as LicenseModule)) {\n\t\tthrow new Error('app-addon-not-valid');\n\t}\n\n\tconst source = getInstallationSourceFromAppStorageItem(app);\n\tswitch (source) {\n\t\tcase 'private':\n\t\t\tif (await License.shouldPreventAction('privateApps')) {\n\t\t\t\tthrow new Error('license-prevented');\n\t\t\t}","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/ee/server/lib/license/canEnableApp.ts#L1-L33","documentation":"_canEnableApp refuses to enable any app while the Apps Engine has not finished initializing: Apps.isInitialized() resolves false. It is the first guard in the enable flow, so it fires regardless of license state whenever the engine is still booting or was never started.","triggerScenarios":"Calling an app-enable path (Apps API methods such as enableApp, or REST routes that enable apps) during server startup before the Apps Engine finished loading, or in tests where the engine was never bootstrapped.","commonSituations":"Server code enabling apps inside Meteor.startup before engine readiness; integration tests that skip engine setup; slow marketplace/app loading creating a startup race window.","solutions":["Wait for engine readiness before enabling: await Apps.isInitialized() (or wait for the apps-engine startup log) and then retry","In tests, initialize the Apps Engine (app manager setup) before calling enable methods","Move enable calls out of early startup hooks into a post-startup callback or queue that drains once the engine is ready"],"exampleFix":"// before\nawait Apps.enableApp(appId); // may throw apps-engine-not-initialized during boot\n\n// after\nwhile (!(await Apps.isInitialized())) {\n\tawait new Promise((resolve) => setTimeout(resolve, 100));\n}\nawait Apps.enableApp(appId);","handlingStrategy":"validation","validationCode":"if (!(await Apps.isInitialized())) {\n\t// queue the enable for after engine startup instead of calling now\n\treturn queueEnableAfterEngineReady(appId);\n}\nawait Apps.enableApp(appId);","typeGuard":null,"tryCatchPattern":"try {\n\tawait Apps.enableApp(appId);\n} catch (err) {\n\tif (err instanceof Error && err.message === 'apps-engine-not-initialized') {\n\t\t// engine still booting: retry on a later tick / after startup event\n\t} else {\n\t\tthrow err;\n\t}\n}","preventionTips":["Never call app enable/disable inside early Meteor.startup blocks; wait for engine-ready","In tests, bootstrap the Apps Engine before exercising enable paths","Log Apps.isInitialized() state during startup to catch slow initializations early"],"tags":["apps-engine","initialization","startup","race-condition"],"backgroundTag":"service-not-initialized","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"}