{"record":{"id":"0d30c0b68f51a03c","repo":"langgenius/dify","slug":"the-number-of-apps-has-reached-the-limit-of-your-s","errorCode":null,"errorMessage":"The number of apps has reached the limit of your subscription.","messagePattern":"The number of apps has reached the limit of your subscription\\.","errorType":"http","errorClass":null,"httpStatus":403,"severity":"warning","filePath":"api/controllers/console/wraps.py","lineNumber":204,"sourceCode":"\n                vector_space = FeatureService.get_vector_space(current_tenant_id)\n                if 0 < vector_space.limit <= vector_space.size:\n                    abort(\n                        403,\n                        \"The capacity of the knowledge storage space has reached the limit of your subscription.\",\n                    )\n                return view(*args, **kwargs)\n\n            features = FeatureService.get_features(current_tenant_id, exclude_vector_space=True)\n            if features.billing.enabled:\n                members = features.members\n                apps = features.apps\n                documents_upload_quota = features.documents_upload_quota\n                annotation_quota_limit = features.annotation_quota_limit\n                if resource == \"members\" and 0 < members.limit <= members.size:\n                    abort(403, \"The number of members has reached the limit of your subscription.\")\n                elif resource == \"apps\" and 0 < apps.limit <= apps.size:\n                    abort(403, \"The number of apps has reached the limit of your subscription.\")\n                elif resource == \"documents\" and 0 < documents_upload_quota.limit <= documents_upload_quota.size:\n                    # The api of file upload is used in the multiple places,\n                    # so we need to check the source of the request from datasets\n                    source = request.args.get(\"source\") or request.form.get(\"source\")\n                    if source == \"datasets\":\n                        abort(403, \"The number of documents has reached the limit of your subscription.\")\n                    else:\n                        return view(*args, **kwargs)\n                elif resource == \"workspace_custom\" and not features.can_replace_logo:\n                    abort(403, \"The workspace custom feature has reached the limit of your subscription.\")\n                elif resource == \"annotation\" and 0 < annotation_quota_limit.limit < annotation_quota_limit.size:\n                    abort(403, \"The annotation quota has reached the limit of your subscription.\")\n                else:\n                    return view(*args, **kwargs)\n\n            return view(*args, **kwargs)\n\n        return decorated","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/wraps.py#L186-L222","documentation":"HTTP 403 from `cloud_edition_billing_resource_check(\"apps\")`. When `resource == \"apps\"` and `0 < apps.limit <= apps.size`, the decorator aborts with `The number of apps has reached the limit of your subscription.` App creation is blocked at the plan's app count ceiling.","triggerScenarios":"Creating a new app on a tenant whose app count equals or exceeds the plan's app limit (limit > 0).","commonSituations":"Free/starter plan with a low app cap; user duplicating apps to template many workflows; bulk import pushing the count over the limit.","solutions":["Upgrade the workspace plan to raise the app limit.","Delete or archive unused apps to free quota before creating new ones.","Surface `FeatureService.get_features(...).apps` (`limit`/`size`) in the UI and disable the 'New App' button at the ceiling.","Confirm the features cache is fresh if the count looks wrong."],"exampleFix":"// before\nawait createApp(payload)  // 403 at app cap\n// after\nconst { apps } = await getFeatures()\nif (apps.limit > 0 && apps.size >= apps.limit) {\n  alert('App limit reached — upgrade or delete an app.')\n} else {\n  await createApp(payload)\n}","handlingStrategy":"validation","validationCode":"from services.feature_service import FeatureService\n\n_, tenant_id = current_account_with_tenant()\nfeatures = FeatureService.get_features(tenant_id, exclude_vector_space=True)\na = features.apps\n\ndef can_create_app() -> bool:\n    return not (a.limit > 0 and a.size >= a.limit)\n\nif not can_create_app():\n    # surface upgrade / delete-app prompt instead of creating\n    ...","typeGuard":"def under_app_cap(limit: int, size: int) -> bool:\n    return not (limit > 0 and size >= limit)","tryCatchPattern":"try:\n    resp = client.post(\"/apps\", ...)\nexcept HTTPError as err:\n    if err.response.status_code == 403 and \"apps\" in err.response.text:\n        # app limit reached — upgrade or delete an app\n        ...\n    raise","preventionTips":["Show app count/limit in the UI; disable New App at the ceiling.","Delete or archive unused apps to free quota.","Upgrade the plan to raise the app limit.","Refresh features cache if the count looks stale."],"tags":["billing","quota","apps","http-403"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}