{"record":{"id":"ac52b06915b638b2","repo":"langgenius/dify","slug":"limit-exceeded-ac52b0","errorCode":"limit_exceeded","errorMessage":"Unable to create workspace because the maximum workspace limit was exceeded","messagePattern":"Unable to create workspace because the maximum workspace limit was exceeded","errorType":"error_code","errorClass":"WorkspacesLimitExceeded","httpStatus":400,"severity":"error","filePath":"api/controllers/console/auth/login.py","lineNumber":172,"sourceCode":"                    )\n                    raise InvalidEmailError()\n            account = _authenticate_account_with_case_fallback(\n                request_email, normalized_email, req_data.password, invite_token\n            )\n        except services.errors.account.AccountLoginError:\n            _log_console_login_failure(email=normalized_email, reason=LoginFailureReason.ACCOUNT_BANNED)\n            raise AccountBannedError()\n        except services.errors.account.AccountPasswordError as exc:\n            AccountService.add_login_error_rate_limit(normalized_email)\n            _log_console_login_failure(email=normalized_email, reason=LoginFailureReason.INVALID_CREDENTIALS)\n            raise AuthenticationFailedError() from exc\n        tenants = TenantService.get_join_tenants(account, session=db.session())\n        if len(tenants) == 0:\n            if (\n                FeatureService.is_workspace_creation_allowed()\n                and not FeatureService.get_license().workspaces.is_available()\n            ):\n                raise WorkspacesLimitExceeded()\n            else:\n                return SimpleResultOptionalDataResponse(\n                    result=\"fail\",\n                    data=\"workspace not found, please contact system admin to invite you to join in a workspace\",\n                ).model_dump(mode=\"json\")\n\n        token_pair = AccountService.login(account=account, session=db.session(), ip_address=extract_remote_ip(request))\n        AccountService.reset_login_error_rate_limit(normalized_email)\n\n        # Create response with cookies instead of returning tokens in body\n        # response-contract:ignore cookie-bearing Flask response\n        response = make_response(\n            SimpleResultOptionalDataResponse(result=\"success\").model_dump(mode=\"json\", exclude_none=True)\n        )\n\n        set_access_token_to_cookie(request, response, token_pair.access_token)\n        set_refresh_token_to_cookie(request, response, token_pair.refresh_token)\n        set_csrf_token_to_cookie(request, response, token_pair.csrf_token)","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/auth/login.py#L154-L190","documentation":"Raised in POST /console/api/login (HTTP 400, code limit_exceeded) when the authenticated account belongs to zero tenants AND workspace creation is allowed by config but the license's workspaces quota is exhausted (FeatureService.get_license().workspaces.is_available() is false). Maps to WorkspacesLimitExceeded.","triggerScenarios":"POST /console/api/login with valid credentials for an account that has no tenants, where is_workspace_creation_allowed() is true and the license/workspace entitlement has no available workspace slots. Common when license seats exist but workspace count is capped.","commonSituations":"Self-hosted or cloud plan with a workspace cap that has been reached; expired or downgraded license reducing the workspace quota; orphaned account whose tenant membership was removed and now cannot create a new workspace; trial license limit hit.","solutions":["Upgrade the license or plan to raise the workspace quota.","Have an admin invite the user to an existing workspace instead of creating a new one.","Delete unused workspaces to free a slot, then retry login.","Confirm FeatureService.get_license().workspaces reflects the current license; refresh/re-apply the license key."],"exampleFix":"# before\nif (FeatureService.is_workspace_creation_allowed()\n        and not FeatureService.get_license().workspaces.is_available()):\n    raise WorkspacesLimitExceeded()\n# after - distinguish code/message so the client can react\nws = FeatureService.get_license().workspaces\nif FeatureService.is_workspace_creation_allowed() and not ws.is_available():\n    raise WorkspacesLimitExceeded(description=f'Workspace limit ({ws.limit}) reached; contact admin to be invited.')","handlingStrategy":"fallback","validationCode":"null","typeGuard":"null","tryCatchPattern":"from controllers.console.error import WorkspacesLimitExceeded\ntry:\n    do_login()\nexcept WorkspacesLimitExceeded:\n    prompt('Workspace limit reached. Ask an admin to invite you to an existing workspace.')","preventionTips":["Provision workspace slots ahead of user growth.","Prefer inviting users into existing workspaces over self-service creation when near the cap.","Monitor license workspace usage and renew/upgrade before exhaustion."],"tags":["auth","login","workspace","license","quota","limit"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}