RocketChat/Rocket.Chat · error · Error

app-addon-not-valid

app-addon-not-valid

Error message

app-addon-not-valid

What it means

Thrown by _canEnableApp when app.info.addon is set and License.hasModule(<addon>) is false — the app declares a required addon module that the current license does not include. Plain Error. Migrated apps return early before this check, so it only affects apps installed after the addon validation was introduced.

Source

Thrown at apps/meteor/ee/server/lib/license/canEnableApp.ts:25

type _canEnableAppDependencies = {
	Apps: typeof Apps;
	License: LicenseImp;
};

export const _canEnableApp = async ({ Apps, License }: _canEnableAppDependencies, app: IAppStorageItem): Promise<void> => {
	if (!(await Apps.isInitialized())) {
		throw new Error('apps-engine-not-initialized');
	}

	// Migrated apps were installed before the validation was implemented
	// so they're always allowed to be enabled
	if (app.migrated) {
		return;
	}

	if (app.info.addon && !License.hasModule(app.info.addon as LicenseModule)) {
		throw new Error('app-addon-not-valid');
	}

	const source = getInstallationSourceFromAppStorageItem(app);
	switch (source) {
		case 'private':
			if (await License.shouldPreventAction('privateApps')) {
				throw new Error('license-prevented');
			}

			break;
		default:
			if (await License.shouldPreventAction('marketplaceApps')) {
				throw new Error('license-prevented');
			}

			const marketplaceInfo = app.marketplaceInfo?.[0];
			if (marketplaceInfo?.isEnterpriseOnly && !License.hasValidLicense()) {
				throw new Error('invalid-license');

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Acquire/apply a license that includes the required addon module and retry.
  2. Install a version of the app that does not require the addon, if available.
  3. If the app was migrated from a pre-validation install, mark app.migrated = true (only valid for genuine migrations).

Example fix

// before
await canEnableApp(app); // throws app-addon-not-valid

// after
if (app.info.addon && !License.hasModule(app.info.addon)) {
  throw new Error(`Apply a license including module '${app.info.addon}' before enabling ${app.info.name}`);
}
Defensive patterns

Strategy: validation

Validate before calling

async function canEnableAddonApp(app: IAppStorageItem): Promise<boolean> {
  return !app.info.addon || License.hasModule(app.info.addon as LicenseModule);
}

Type guard

const declaresAddon = (app: IAppStorageItem): boolean => Boolean(app?.info?.addon);

Try / catch

try { await canEnableApp(app); } catch (e) {
  if (e instanceof Error && e.message === 'app-addon-not-valid') { /* apply license with module or use other app version */ } else throw e;
}

Prevention

When it happens

Trigger: Enabling an app whose manifest declares an addon module (e.g. a premium/bundled module) on a server whose license lacks that module; installing a marketplace app that later gained an addon requirement.

Common situations: License downgrade removed the module; app updated to require a new addon; community edition used to enable a premium app.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/9cafc33e00ad0a0a. Report an issue: GitHub.