{"record":{"id":"bbbd84259ca1d659","repo":"elunez/eladmin","slug":"menu-with-componentname-existed","errorCode":null,"errorMessage":"Menu with componentName {} existed","messagePattern":"Menu with componentName (.+?) existed","errorType":"exception","errorClass":"EntityExistException","httpStatus":400,"severity":"error","filePath":"eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java","lineNumber":128,"sourceCode":"        if (CollUtil.isEmpty(menus)){\n            List<RoleSmallDto> roles = roleService.findByUsersId(currentUserId);\n            Set<Long> roleIds = roles.stream().map(RoleSmallDto::getId).collect(Collectors.toSet());\n            LinkedHashSet<Menu> data = menuRepository.findByRoleIdsAndTypeNot(roleIds, 2);\n            menus = new ArrayList<>(data);\n            redisUtils.set(key, menus, 1, TimeUnit.DAYS);\n        }\n        return menus.stream().map(menuMapper::toDto).collect(Collectors.toList());\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public void create(Menu resources) {\n        if(menuRepository.findByTitle(resources.getTitle()) != null){\n            throw new EntityExistException(Menu.class,\"title\",resources.getTitle());\n        }\n        if(StringUtils.isNotBlank(resources.getComponentName())){\n            if(menuRepository.findByComponentName(resources.getComponentName()) != null){\n                throw new EntityExistException(Menu.class,\"componentName\",resources.getComponentName());\n            }\n        }\n        if (Long.valueOf(0L).equals(resources.getPid())) {\n            resources.setPid(null);\n        }\n        if(resources.getIFrame()){\n            if (!(resources.getPath().toLowerCase().startsWith(HTTP_PRE)||resources.getPath().toLowerCase().startsWith(HTTPS_PRE))) {\n                throw new BadRequestException(BAD_REQUEST);\n            }\n        }\n        menuRepository.save(resources);\n        // 计算子节点数目\n        resources.setSubCount(0);\n        // 更新父节点菜单数目\n        updateSubCnt(resources.getPid());\n    }\n\n    @Override","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/elunez/eladmin/blob/55fbf705956949697dbd68bf9003776609d3d029/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java#L110-L146","documentation":"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.","triggerScenarios":"POST /api/menus with a non-blank componentName equal to an existing menu's componentName (only checked when StringUtils.isNotBlank).","commonSituations":"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.","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."],"exampleFix":"// before: duplicated keep-alive name\nmenu.setComponentName(\"UserManagement\"); // already used\n\n// after: unique name aligned with the Vue page\nmenu.setComponentName(\"OnlineUserManagement\");","handlingStrategy":"validation","validationCode":"if (StringUtils.isNotBlank(form.componentName)) {\n    Menu dup = menuRepository.findByComponentName(form.componentName);\n    if (dup != null) throw new IllegalArgumentException(\"componentName taken: \" + dup.getTitle());\n}","typeGuard":null,"tryCatchPattern":"catch (EntityExistException e) { if (e.getMessage().startsWith(\"Menu with componentName\")) { formErrors.componentName = '已被其他菜单使用'; } }","preventionTips":["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"],"tags":["eladmin","menu","component-name","keep-alive","duplicate"],"backgroundTag":null,"analyzedSha":"55fbf705956949697dbd68bf9003776609d3d029","analyzedAt":"2026-08-14T11:56:12.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}