elunez/eladmin · warning · BadRequestException
A new menu cannot already have an ID
Error message
A new menu cannot already have an ID
What it means
Thrown by MenuController.createMenu (line 128) when the POST /api/menus body includes a non-null id. Menus are hierarchical entities whose ids are database-assigned; the guard enforces the create-before-identity contract and returns 400 before menuService.create runs, preventing accidental row shadowing.
Source
Thrown at eladmin-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java:128
menu.setSubCount(menu.getSubCount() - 1);
}
}
menuDtos.addAll(menuDtoList);
}
// 编辑菜单时不显示自己以及自己下级的数据,避免出现PID数据环形问题
menuDtos = menuDtos.stream().filter(i -> !ids.contains(i.getId())).collect(Collectors.toSet());
return new ResponseEntity<>(menuService.buildTree(new ArrayList<>(menuDtos)),HttpStatus.OK);
}
return new ResponseEntity<>(menuService.getMenus(null),HttpStatus.OK);
}
@Log("新增菜单")
@ApiOperation("新增菜单")
@PostMapping
@PreAuthorize("@el.check('menu:add')")
public ResponseEntity<Object> createMenu(@Validated @RequestBody Menu resources){
if (resources.getId() != null) {
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
}
menuService.create(resources);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@Log("修改菜单")
@ApiOperation("修改菜单")
@PutMapping
@PreAuthorize("@el.check('menu:edit')")
public ResponseEntity<Object> updateMenu(@Validated(Menu.Update.class) @RequestBody Menu resources){
menuService.update(resources);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@Log("删除菜单")
@ApiOperation("删除菜单")
@DeleteMapping
@PreAuthorize("@el.check('menu:del')")View on GitHub (pinned to 55fbf70595)
Solutions
- Remove id from the payload before POST /api/menus; keep only pid and the fields you want.
- When duplicating a menu, map explicitly to a new object instead of POSTing the fetched entity.
- Reset the menu form (id = null, keep pid if creating a child) when the dialog opens in create mode.
Example fix
// before (duplicate a menu by posting the fetched row)
axios.post('/api/menus', this.selectedMenu)
// after
const { id, children, ...payload } = this.selectedMenu;
axios.post('/api/menus', payload) Defensive patterns
Strategy: validation
Validate before calling
const { id, children, createTime, ...payload } = selectedMenu;
axios.post('/api/menus', payload); // duplication without id Type guard
const isCreatePayload = (m) => m.id === undefined || m.id === null;
Prevention
- When duplicating menus, map to an explicit new object.
- Exclude the current node from the parent picker (also prevents pid = id).
When it happens
Trigger: Menu management tree dialog switching from edit to create without clearing the form; POSTing a Menu object fetched from GET /api/menus (e.g. to duplicate a menu); tooling that copies a whole menu subtree including ids.
Common situations: Front-end reuses the selected tree node (with id) as the base for a new sibling menu; menu duplication workflows; copying menu configuration between instances.
Related errors
- A new dept cannot already have an ID
- A new dict cannot already have an ID
- A new dictDetail cannot already have an ID
- A new job cannot already have an ID
- A new role cannot already have an ID
AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14).
Data as JSON: /api/errors/47ea1b14525cf1fd.
Report an issue: GitHub.