elunez/eladmin · error · EntityExistException
Menu with componentName {} existed
Error message
Menu with componentName {} existed What it means
EntityExistException thrown in MenuServiceImpl.create when componentName is non-blank and another menu already uses it. componentName is the Vue keep-alive route name, so eladmin enforces global uniqueness to prevent two routes registered under the same component name, which would break tag-view caching and navigation.
Source
Thrown at eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java:128
if (CollUtil.isEmpty(menus)){
List<RoleSmallDto> roles = roleService.findByUsersId(currentUserId);
Set<Long> roleIds = roles.stream().map(RoleSmallDto::getId).collect(Collectors.toSet());
LinkedHashSet<Menu> data = menuRepository.findByRoleIdsAndTypeNot(roleIds, 2);
menus = new ArrayList<>(data);
redisUtils.set(key, menus, 1, TimeUnit.DAYS);
}
return menus.stream().map(menuMapper::toDto).collect(Collectors.toList());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void create(Menu resources) {
if(menuRepository.findByTitle(resources.getTitle()) != null){
throw new EntityExistException(Menu.class,"title",resources.getTitle());
}
if(StringUtils.isNotBlank(resources.getComponentName())){
if(menuRepository.findByComponentName(resources.getComponentName()) != null){
throw new EntityExistException(Menu.class,"componentName",resources.getComponentName());
}
}
if (Long.valueOf(0L).equals(resources.getPid())) {
resources.setPid(null);
}
if(resources.getIFrame()){
if (!(resources.getPath().toLowerCase().startsWith(HTTP_PRE)||resources.getPath().toLowerCase().startsWith(HTTPS_PRE))) {
throw new BadRequestException(BAD_REQUEST);
}
}
menuRepository.save(resources);
// 计算子节点数目
resources.setSubCount(0);
// 更新父节点菜单数目
updateSubCnt(resources.getPid());
}
@OverrideView on GitHub (pinned to 55fbf70595)
Solutions
- Give the new menu a distinct componentName matching the actual Vue component's name in the front-end project.
- Leave componentName blank if the page does not need keep-alive caching — the check is skipped for blank values.
- Search existing menus (GET /api/menus) for the componentName and rename or delete the conflicting entry first.
Example fix
// before: duplicated keep-alive name
menu.setComponentName("UserManagement"); // already used
// after: unique name aligned with the Vue page
menu.setComponentName("OnlineUserManagement"); Defensive patterns
Strategy: validation
Validate before calling
if (StringUtils.isNotBlank(form.componentName)) {
Menu dup = menuRepository.findByComponentName(form.componentName);
if (dup != null) throw new IllegalArgumentException("componentName taken: " + dup.getTitle());
} Try / catch
catch (EntityExistException e) { if (e.getMessage().startsWith("Menu with componentName")) { formErrors.componentName = '已被其他菜单使用'; } } Prevention
- One componentName per Vue page — never reuse across menus
- Leave componentName empty for pages that don't need keep-alive
- Derive componentName from the Vue component's name option automatically
When it happens
Trigger: POST /api/menus with a non-blank componentName equal to an existing menu's componentName (only checked when StringUtils.isNotBlank).
Common situations: Copy-pasting an existing menu definition and editing only the title/path; front-end developers naming two pages with the same Vue component name; seeded menus from SQL dumps colliding with manually added ones.
Related errors
- Menu with title {} existed
- A new menu cannot already have an ID
- Job with name {} existed
- 外链必须以http://或者https://开头
- 上级不能为自己
AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14).
Data as JSON: /api/errors/bbbd84259ca1d659.
Report an issue: GitHub.