Budibase/budibase · error
Features do not exist for planType=${planType}
Error message
Features do not exist for planType=${planType} What it means
getOfflineFeatures looks up the plan's features in the hard-coded SELF_FEATURES table for self-hosted offline licenses. If the license's plan.type has no entry there (e.g. a cloud-only plan like Premium used on self host), this plain Error is thrown. It means the offline license references a plan that self host does not support.
Source
Thrown at packages/pro/src/sdk/licensing/licenses/features.ts:150
Feature.AI_CUSTOM_CONFIGS,
Feature.PWA,
Feature.CUSTOM_APP_SCRIPTS,
Feature.PDF,
Feature.BUDIBASE_AI,
Feature.RECAPTCHA,
Feature.PKCE_OIDC,
Feature.TRANSLATIONS,
Feature.MICROFRONTEND,
],
}
export function getOfflineFeatures(planType: PlanType): Feature[] {
function readFeatures(planFeatures: PlanFeatures): Feature[] {
const quotas = planFeatures[planType]
if (!quotas) {
// e.g. Premium plan doesn't exist on self host
throw new Error(`Features do not exist for planType=${planType}`)
}
return quotas
}
return readFeatures(SELF_FEATURES)
}
View on GitHub (pinned to a81a902e9a)
Solutions
- Use an offline license token whose plan type is valid for self host (e.g. the self-host tier for your subscription), not a cloud-only plan.
- Regenerate the offline token from the account portal for the correct plan/hosting combination.
- Upgrade Budibase/pro so the runtime's SELF_FEATURES map includes the plan type in the token.
- Check the planType value in the decoded license token to confirm which plan it grants.
Example fix
// before
const features = getOfflineFeatures(license.plan.type) // throws for Premium
// after
const SELF_PLAN_TYPES = Object.keys(SELF_FEATURES) as PlanType[]
if (!SELF_PLAN_TYPES.includes(license.plan.type)) {
console.warn(`Plan ${license.plan.type} unsupported on self host — skipping offline features`)
} else {
const features = getOfflineFeatures(license.plan.type)
} Defensive patterns
Strategy: validation
Validate before calling
import { SELF_FEATURES } from "../licensing/licenses/features"
function planSupportedOnSelfHost(planType: PlanType): boolean {
return Boolean(SELF_FEATURES[planType])
}
if (!planSupportedOnSelfHost(license.plan.type)) {
throw new Error(`Plan ${license.plan.type} is not available on self host`)
} Type guard
function hasSelfHostFeatures(planType: PlanType): planType is keyof typeof SELF_FEATURES {
return Boolean(SELF_FEATURES[planType])
} Try / catch
try {
const license = await getOfflineLicense()
} catch (e) {
if (e instanceof Error && e.message.startsWith("Features do not exist for planType=")) {
// offline token uses a cloud-only plan — request a self-host token
} else throw e
} Prevention
- Only issue offline tokens for plans that exist on self host.
- Match Budibase/pro versions between token generation and consumption.
- Decode tokens and check plan.type before offline activation.
When it happens
Trigger: Calling getOfflineFeatures(planType) (indirectly via enrichLicense → getOfflineLicense after verifyOfflineLicenseToken succeeds) with a PlanType that has no key in SELF_FEATURES.
Common situations: Applying an offline license token generated for a cloud plan (e.g. Premium/enterprise cloud-only tier) to a self-hosted installation; a PlanType added in a newer Budibase version but the running version's SELF_FEATURES map predates it (or vice versa — token from newer version, older runtime); hand-edited license tokens.
Related errors
- Offline license has expired. expireAt=${license.expireAt}
- Invalid offline license
- Invalid offline license token
- Offline license has expired
- Offline license does not match this installation
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/6c7aa945735f3817.
Report an issue: GitHub.