jeecgboot/JeecgBoot · error · JeecgBootException

未找到菜单信息

Error message

未找到菜单信息

What it means

Thrown by SysPermissionServiceImpl.deletePermission (real/hard delete) when this.getById(id) returns null — the menu/permission to delete does not exist. This JeecgBootException prevents cascading deletes on a non-existent record. The method is transactional and evicts the data-permissions cache.

Source

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

		sysPermissionMapper.backupVue2Menu();
		sysPermissionMapper.changeVue3Menu();
	}

	@Override
	public List<TreeModel> queryListByParentId(String parentId) {
		return sysPermissionMapper.queryListByParentId(parentId);
	}

	/**
	  * 真实删除
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	@CacheEvict(value = CacheConstant.SYS_DATA_PERMISSIONS_CACHE,allEntries=true)
	public void deletePermission(String id) throws JeecgBootException {
		SysPermission sysPermission = this.getById(id);
		if(sysPermission==null) {
			throw new JeecgBootException("未找到菜单信息");
		}
		String pid = sysPermission.getParentId();
		if(oConvertUtils.isNotEmpty(pid)) {
			Long count = this.count(new QueryWrapper<SysPermission>().lambda().eq(SysPermission::getParentId, pid));
			if(count==1) {
				//若父节点无其他子节点,则该父节点是叶子节点
				this.sysPermissionMapper.setMenuLeaf(pid, 1);
			}
		}
		sysPermissionMapper.deleteById(id);
		// 该节点可能是子节点但也可能是其它节点的父节点,所以需要级联删除
		this.removeChildrenBy(sysPermission.getId());
		//关联删除
		Map map = new HashMap(5);
		map.put("permission_id",id);
		//删除数据规则
		this.deletePermRuleByPermId(id);
		//删除角色授权表

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Add frontend debounce/loading state on the delete button to prevent duplicate requests.
  2. Refresh the menu/permission tree after a delete before attempting another.
  3. If calling programmatically, verify the permission exists before calling deletePermission.
  4. Consider catching JeecgBootException at the controller to return a friendly 'already deleted' message.

Example fix

// before
SysPermission sysPermission = this.getById(id);
if (sysPermission == null) {
    throw new JeecgBootException("未找到菜单信息");
}

// after — controller handles gracefully
try {
    permissionService.deletePermission(id);
} catch (JeecgBootException e) {
    if (e.getMessage().contains("未找到")) {
        return Result.OK("菜单已不存在,可能已被删除");
    }
    throw e;
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate permission exists before deleting
SysPermission perm = permissionService.getById(id);
if (perm == null) {
    return Result.OK("菜单已不存在,可能已被删除");
}
permissionService.deletePermission(id);

Type guard

public boolean isPermissionExists(String id) {
    if (id == null || id.trim().isEmpty()) return false;
    return permissionService.getById(id) != null;
}

Try / catch

try {
    permissionService.deletePermission(id);
} catch (JeecgBootException e) {
    if (e.getMessage().contains("未找到菜单信息")) {
        return Result.OK("菜单已不存在,可能已被删除");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling deletePermission with a permission ID that was already deleted (physically), doesn't exist, or is from a different tenant. The ID comes from the controller's delete endpoint.

Common situations: Double-click on a delete button causing two delete requests for the same menu; a menu was already hard-deleted by another admin; a stale menu ID from an outdated frontend menu tree.

Related errors


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