jeecgboot/JeecgBoot · error · JeecgBootException

离职失败,租户不存在

Error message

离职失败,租户不存在

What it means

Thrown by SysUserServiceImpl.userQuit when TenantContext.getTenant() resolves to 0 (default/empty). Quitting requires a tenant context because it updates sys_user_tenant status to USER_TENANT_QUIT for that tenant.

Source

Thrown at jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserServiceImpl.java:957

		loginUser.setOrgId(this.getDepartIdByOrCode(sysUser.getOrgCode()));
		// 查询当前登录用户的角色code(多个逗号分割)
		loginUser.setRoleCode(this.getJoinRoleCodeByUserId(sysUser.getId()));
		return loginUser;
	}

    @Override
    @CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
    @Transactional(rollbackFor = Exception.class)
    public void userQuit(String username) {
        SysUser sysUser = userMapper.getUserByName(username);
        if(null == sysUser){
            throw new JeecgBootException("离职失败,该用户已不存在");
        }
		// 代码逻辑说明: [QQYUN-3951]租户用户离职重构------------
		int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
		//更新用户租户表的状态为离职状态
		if(tenantId==0){
			throw new JeecgBootException("离职失败,租户不存在");
		}
		LambdaQueryWrapper<SysUserTenant> query = new LambdaQueryWrapper<>();
		query.eq(SysUserTenant::getUserId,sysUser.getId());
		query.eq(SysUserTenant::getTenantId,tenantId);
		SysUserTenant userTenant = new SysUserTenant();
		userTenant.setStatus(CommonConstant.USER_TENANT_QUIT);
		userTenantMapper.update(userTenant,query);
    }

    @Override
    public List<SysUser> getQuitList(Integer tenantId) {
        return userMapper.getTenantQuitList(tenantId);
    }

    @Override
    public void updateStatusAndFlag(List<String> userIds, SysUser sysUser) {
        userMapper.updateStatusAndFlag(userIds,sysUser);
    }

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Ensure the tenant context header is set on the request before calling userQuit.
  2. Verify the tenant interceptor/filter populates TenantContext for this route.
  3. If the user truly has no tenant, quit is not the right operation - use account deletion instead.
  4. Confirm TenantContext.getTenant() returns the intended tenant id, not the default 0.

Example fix

// before: no tenant header
userService.userQuit(username); // tenantId==0 -> throws

// after: set tenant context (interceptor) or pass explicitly
TenantContext.setTenant(String.valueOf(targetTenantId));
userService.userQuit(username);
Defensive patterns

Strategy: validation

Validate before calling

int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
if (tenantId == 0) return Result.error("缺少租户上下文");
userService.userQuit(username);

Type guard

boolean hasTenantContext() {
  return oConvertUtils.getInt(TenantContext.getTenant(), 0) != 0;
}

Try / catch

try { userService.userQuit(username); }
catch (JeecgBootException e) {
  if (e.getMessage().contains("租户不存在")) return Result.error("请设置租户标识后重试");
  throw e;
}

Prevention

When it happens

Trigger: userQuit invoked with no tenant in the request header/context (TenantContext.getTenant returns null or '0', oConvertUtils.getInt defaults to 0).

Common situations: The X-Tenant-Id header / tenant context was not set (e.g. admin backdoor without tenant header); the interceptor that sets TenantContext was bypassed; the user is genuinely non-tenant and quit is not supported; token filter dropped tenant info.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/768b1e7180ff8de6. Report an issue: GitHub.