langgenius/dify · warning

This feature requires a paid plan.

Error message

This feature requires a paid plan.

What it means

HTTP 403 from the `cloud_edition_billing_paid_plan_required` decorator (controllers/console/wraps.py). It looks up the current tenant's billing info via `BillingService.get_info`; if billing is not enabled or the subscription plan is neither `PROFESSIONAL` nor `TEAM`, it aborts with `This feature requires a paid plan.`

Source

Thrown at api/controllers/console/wraps.py:172

    def decorated(*args: P.args, **kwargs: P.kwargs):
        if dify_config.DEPLOYMENT_EDITION == DeploymentEdition.CLOUD:
            abort(404)

        return view(*args, **kwargs)

    return decorated


def cloud_edition_billing_paid_plan_required[**P, R](view: Callable[P, R]) -> Callable[P, R]:
    @wraps(view)
    def decorated(*args: P.args, **kwargs: P.kwargs):
        _, current_tenant_id = current_account_with_tenant()
        billing_info = BillingService.get_info(current_tenant_id, exclude_vector_space=True)
        if not billing_info["enabled"] or billing_info["subscription"]["plan"] not in (
            CloudPlan.PROFESSIONAL,
            CloudPlan.TEAM,
        ):
            abort(403, "This feature requires a paid plan.")
        return view(*args, **kwargs)

    return decorated


def cloud_edition_billing_resource_check[**P, R](resource: str) -> Callable[[Callable[P, R]], Callable[P, R]]:
    def interceptor(view: Callable[P, R]):
        @wraps(view)
        def decorated(*args: P.args, **kwargs: P.kwargs):
            _, current_tenant_id = current_account_with_tenant()
            if resource == "vector_space":
                if dify_config.DEPLOYMENT_EDITION != DeploymentEdition.CLOUD:
                    return view(*args, **kwargs)

                vector_space = FeatureService.get_vector_space(current_tenant_id)
                if 0 < vector_space.limit <= vector_space.size:
                    abort(
                        403,

View on GitHub (pinned to ef8544b173)

Solutions

  1. Upgrade the workspace to a PROFESSIONAL or TEAM plan.
  2. Verify `BillingService` is correctly wired and returning `enabled=true` for the tenant.
  3. Gate the paid feature in the UI behind the plan flag from `/system-features`.
  4. If you believe billing is misconfigured, confirm the billing service connection and tenant subscription state.

Example fix

// before
// free-plan tenant calls paid-only endpoint -> 403
// after
// upgrade plan, or gate UI: if (features.billing.subscription.plan !== 'professional' && !== 'team') hideFeature()
Defensive patterns

Strategy: validation

Validate before calling

from services.billing_service import BillingService

_, tenant_id = current_account_with_tenant()
info = BillingService.get_info(tenant_id, exclude_vector_space=True)
plan = info["subscription"]["plan"]

def on_paid_plan() -> bool:
    return info["enabled"] and plan in (CloudPlan.PROFESSIONAL, CloudPlan.TEAM)

if not on_paid_plan():
    # do not call paid-only route
    ...

Type guard

PAID = {"professional", "team"}
def is_paid_plan(plan: str | None) -> bool:
    return (plan or "").lower() in PAID

Try / catch

try:
    resp = client.get("/paid-only-route")
except HTTPError as err:
    if err.response.status_code == 403:
        # show upgrade CTA
        ...
    raise

Prevention

When it happens

Trigger: Calling any route wrapped with `@cloud_edition_billing_paid_plan_required` from a tenant on the free/starter plan, with billing disabled, or with no subscription.

Common situations: Free-plan tenant hitting a paid-only feature (e.g. advanced model/analytics); trial expired; sandbox workspace without a paid subscription; billing service misconfigured so `enabled` reads false.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/b93cb056ff2852a8. Report an issue: GitHub.