{"record":{"id":"6af43877327f9a1a","repo":"Budibase/budibase","slug":"feature-disabled","errorCode":"FEATURE_DISABLED","errorMessage":"Feature disabled: '${featureFlag}'","messagePattern":"Feature disabled: '(.+?)'","errorType":"error_code","errorClass":"FeatureDisabledWarning","httpStatus":400,"severity":"warning","filePath":"packages/pro/src/sdk/features/features.ts","lineNumber":27,"sourceCode":"  license?: License\n) {\n  if (!Array.isArray(featureFlags)) {\n    featureFlags = [featureFlags]\n  }\n  if (!license) {\n    license = await cache.getCachedLicense()\n  }\n  for (let flag of featureFlags) {\n    if (!license?.features.includes(flag)) {\n      return false\n    }\n  }\n  return true\n}\n\nexport async function checkFeature(featureFlag: Feature, license?: License) {\n  if (!(await areFeaturesEnabled(featureFlag, license))) {\n    throw new FeatureDisabledWarning(featureFlag)\n  }\n}\n\nexport async function checkFeatures(\n  featureFlags: Feature[],\n  license?: License\n) {\n  if (!(await areFeaturesEnabled(featureFlags, license))) {\n    const flagsMsg = featureFlags.join(\", \")\n    throw new FeatureDisabledWarning(flagsMsg)\n  }\n}\n\n// BACKUPS\n\nexport function checkBackups<Args extends any[], Return>(\n  targetFunction: (...parameters: Args) => Return\n): (...parameters: Args) => Promise<Return> {","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/pro/src/sdk/features/features.ts#L9-L45","documentation":"checkFeature asserts that a single licensed feature flag is enabled for the tenant by delegating to areFeaturesEnabled; if the license lacks the feature it throws a FeatureDisabledWarning carrying code FEATURE_DISABLED. The message embeds the specific Feature enum value that is unavailable, letting callers branch on which feature failed.","triggerScenarios":"Calling requireFeature or checkFeature (directly or via checkBackups/update wrappers) with a Feature the tenant's license does not include, e.g. invoking a backup/SCIM/custom-branding flow on a plan lacking that feature.","commonSituations":"Free or lower-tier plan attempting Pro-only functionality; expired or downgraded license; self-hosted install without an applied license key; stale cached license missing newly purchased features.","solutions":["Upgrade the tenant's license to one that includes the flagged feature, or start a trial that grants it.","Refresh the cached license so newly purchased features are visible to licensing checks.","Wrap the feature-gated code in a check for the feature (or catch FeatureDisabledWarning) and degrade gracefully.","Verify the correct tenant/workspace context is being used so the right license is evaluated."],"exampleFix":"// before\nawait requireFeature(Feature.SCIM)\n// after\nif (await areFeaturesEnabled(Feature.SCIM)) {\n  await requireFeature(Feature.SCIM)\n} else {\n  // show upsell / disable feature in UI\n}","handlingStrategy":"try-catch","validationCode":"const enabled = await areFeaturesEnabled(featureFlag)\nif (!enabled) { /* disable feature or show upsell */ }","typeGuard":null,"tryCatchPattern":"try {\n  await requireFeature(Feature.SCIM)\n  runScimFlow()\n} catch (err) {\n  if (err instanceof FeatureDisabledWarning) {\n    // degrade gracefully / show upgrade prompt\n  } else throw err\n}","preventionTips":["Prefer areFeaturesEnabled lookups for UI gating over throwing checks","Refresh the cached license after plan changes","Check the tenant context is correct before feature checks"],"tags":["licensing","feature-flag","pro"],"backgroundTag":"license-feature-missing","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}