{"record":{"id":"38fa8c074880104a","repo":"jeecgboot/JeecgBoot","slug":"assignedowen","errorCode":null,"errorMessage":"assignedOwen","messagePattern":"assignedOwen","errorType":"exception","errorClass":"JeecgBootException","httpStatus":null,"severity":"warning","filePath":"jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantServiceImpl.java","lineNumber":347,"sourceCode":"               return 1000;\n           }\n       }\n   }\n\n\n    @Override\n    public void exitUserTenant(String userId, String username, String tenantId) {\n        int tId = Integer.parseInt(tenantId);\n        //获取所有租户信息\n        List<String> userIdsByTenantId = userTenantMapper.getUserIdsByTenantId(tId);\n        //查询当前租户是否为拥有者\n        SysTenant sysTenant = tenantMapper.selectById(tId);\n        //如果是拥有着\n        if (username.equals(sysTenant.getCreateBy())) {\n            //判断当前租户信息位数\n            if (null != userIdsByTenantId && userIdsByTenantId.size() > 1) {\n                //需要指配拥有者\n                throw new JeecgBootException(\"assignedOwen\");\n            } else if (null != userIdsByTenantId && userIdsByTenantId.size() == 1) {\n                //只有拥有者的时候需要去注销租户\n                throw new JeecgBootException(\"cancelTenant\");\n            } else {\n                throw new JeecgBootException(\"退出租户失败，租户信息已不存在\");\n            }\n        } else {\n            //不是拥有者直接删除\n            this.leaveTenant(userId, tenantId);\n            this.leveUserProcess(userId, tenantId);\n        }\n    }\n\n    @Override\n    public void changeOwenUserTenant(String userId, String tId) {\n        //查询当前用户是否存在该租户下\n        // 代码逻辑说明: 租户id应该是传过来的，不应该是当前租户的------------\n        int tenantId = oConvertUtils.getInt(tId, 0);","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantServiceImpl.java#L329-L365","documentation":"exitUserTenant throws the literal string 'assignedOwen' (a typo for 'assignedOwner') as a sentinel/control-flow signal when the exiting user is the tenant creator (sysTenant.createBy equals username) AND the tenant has more than one member. This is not a user-facing error — the frontend controller catches it to redirect to the 'assign new owner' workflow. JeecgBootException is abused as a flow-control channel.","triggerScenarios":"The tenant owner (createBy) calls exit-user-tenant while other members still belong to the tenant (userIdsByTenantId.size() > 1). The service refuses to leave the tenant ownerless and signals that a successor must be designated first.","commonSituations":"Owner clicks 'exit tenant' in the UI without first transferring ownership; an automation/script calls exitUserTenant for the owner without the assign-owner step; the frontend handler for 'assignedOwen' is missing or misnamed due to the typo.","solutions":["Follow the owner-transfer flow: call changeOwenUserTenant(newOwnerId, tenantId) to assign a new owner, then exit.","If consuming the API directly, catch JeecgBootException with message 'assignedOwen' and prompt the user to choose a successor.","Fix the sentinel typo upstream to 'assignedOwner' and update all matching catch sites (defensive: match on a constant, not the literal).","As owner, first remove/transfer other members if you intend to exit, reducing size to 1 (which routes to cancelTenant)."],"exampleFix":"// before\ntenantService.exitUserTenant(userId, username, tenantId);\n\n// after\ntry {\n    tenantService.exitUserTenant(userId, username, tenantId);\n} catch (JeecgBootException e) {\n    if (\"assignedOwen\".equals(e.getMessage())) {\n        // redirect to assign-new-owner flow\n        return Result.OK(\"ASSIGN_OWNER\", null);\n    }\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    tenantService.exitUserTenant(userId, username, tenantId);\n} catch (JeecgBootException e) {\n    if (\"assignedOwen\".equals(e.getMessage())) {\n        return Result.OK(\"ASSIGN_OWNER\", null);\n    }\n    throw e;\n}","preventionTips":["Always transfer ownership (changeOwenUserTenant) before the owner exits a multi-member tenant.","Handle the 'assignedOwen' sentinel explicitly in the controller/frontend.","Refactor upstream to use a result code instead of a thrown sentinel string."],"tags":["tenant","control-flow","ownership","jeecg-boot","code-smell"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}