{"record":{"id":"b93cb056ff2852a8","repo":"langgenius/dify","slug":"this-feature-requires-a-paid-plan","errorCode":null,"errorMessage":"This feature requires a paid plan.","messagePattern":"This feature requires a paid plan\\.","errorType":"http","errorClass":null,"httpStatus":403,"severity":"warning","filePath":"api/controllers/console/wraps.py","lineNumber":172,"sourceCode":"    def decorated(*args: P.args, **kwargs: P.kwargs):\n        if dify_config.DEPLOYMENT_EDITION == DeploymentEdition.CLOUD:\n            abort(404)\n\n        return view(*args, **kwargs)\n\n    return decorated\n\n\ndef cloud_edition_billing_paid_plan_required[**P, R](view: Callable[P, R]) -> Callable[P, R]:\n    @wraps(view)\n    def decorated(*args: P.args, **kwargs: P.kwargs):\n        _, current_tenant_id = current_account_with_tenant()\n        billing_info = BillingService.get_info(current_tenant_id, exclude_vector_space=True)\n        if not billing_info[\"enabled\"] or billing_info[\"subscription\"][\"plan\"] not in (\n            CloudPlan.PROFESSIONAL,\n            CloudPlan.TEAM,\n        ):\n            abort(403, \"This feature requires a paid plan.\")\n        return view(*args, **kwargs)\n\n    return decorated\n\n\ndef cloud_edition_billing_resource_check[**P, R](resource: str) -> Callable[[Callable[P, R]], Callable[P, R]]:\n    def interceptor(view: Callable[P, R]):\n        @wraps(view)\n        def decorated(*args: P.args, **kwargs: P.kwargs):\n            _, current_tenant_id = current_account_with_tenant()\n            if resource == \"vector_space\":\n                if dify_config.DEPLOYMENT_EDITION != DeploymentEdition.CLOUD:\n                    return view(*args, **kwargs)\n\n                vector_space = FeatureService.get_vector_space(current_tenant_id)\n                if 0 < vector_space.limit <= vector_space.size:\n                    abort(\n                        403,","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/wraps.py#L154-L190","documentation":"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.`","triggerScenarios":"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.","commonSituations":"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.","solutions":["Upgrade the workspace to a PROFESSIONAL or TEAM plan.","Verify `BillingService` is correctly wired and returning `enabled=true` for the tenant.","Gate the paid feature in the UI behind the plan flag from `/system-features`.","If you believe billing is misconfigured, confirm the billing service connection and tenant subscription state."],"exampleFix":"// before\n// free-plan tenant calls paid-only endpoint -> 403\n// after\n// upgrade plan, or gate UI: if (features.billing.subscription.plan !== 'professional' && !== 'team') hideFeature()","handlingStrategy":"validation","validationCode":"from services.billing_service import BillingService\n\n_, tenant_id = current_account_with_tenant()\ninfo = BillingService.get_info(tenant_id, exclude_vector_space=True)\nplan = info[\"subscription\"][\"plan\"]\n\ndef on_paid_plan() -> bool:\n    return info[\"enabled\"] and plan in (CloudPlan.PROFESSIONAL, CloudPlan.TEAM)\n\nif not on_paid_plan():\n    # do not call paid-only route\n    ...","typeGuard":"PAID = {\"professional\", \"team\"}\ndef is_paid_plan(plan: str | None) -> bool:\n    return (plan or \"\").lower() in PAID","tryCatchPattern":"try:\n    resp = client.get(\"/paid-only-route\")\nexcept HTTPError as err:\n    if err.response.status_code == 403:\n        # show upgrade CTA\n        ...\n    raise","preventionTips":["Upgrade to PROFESSIONAL/TEAM for paid-only features.","Gate paid UI on the plan flag from /system-features.","Verify BillingService returns enabled=true for the tenant.","Refresh subscription state after plan changes."],"tags":["billing","plan-gate","cloud-only","http-403"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}