paascloud/paascloud-master · error · UacBizException
UAC10013008
UAC10013008
Error message
删除菜单失败, menuId=%s
What it means
UacBizException UAC10013008 thrown when deleteUacMenuById's final delete (uacMenuMapper.deleteByPrimaryKey(id)) affects fewer than 1 row, meaning the menu row disappeared between the existence check and the delete, or the delete statement failed to match. An error log '删除菜单失败 menuId=...' is written first.
Solutions
- Verify the menu no longer exists — if it is already gone, treat the delete as idempotent success and skip the error.
- Deduplicate delete requests on the client (disable button after first click) to avoid racing deletes.
- Confirm the deleteByPrimaryKey SQL matches rows by the correct primary key column in the mapper XML.
- Inspect DB logs for row-lock or transaction issues around the delete.
Example fix
// before: fail hard on 0 rows
int result = uacMenuMapper.deleteByPrimaryKey(id);
if (result < 1) { throw new UacBizException(ErrorCodeEnum.UAC10013008, id); }
// after: idempotent delete
int result = uacMenuMapper.deleteByPrimaryKey(id);
if (result < 1 && uacMenuMapper.selectByPrimaryKey(id) != null) {
throw new UacBizException(ErrorCodeEnum.UAC10013008, id);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (uacMenuMapper.selectByPrimaryKey(id) == null) { return; /* already gone */ } Type guard
boolean menuStillExists(Long id) { return uacMenuMapper.selectByPrimaryKey(id) != null; } Try / catch
try {
uacMenuService.deleteUacMenuById(id);
} catch (UacBizException e) {
if ("UAC10013008".equals(e.getCode()) && uacMenuMapper.selectByPrimaryKey(id) == null) {
return; // raced with another delete; treat as success
}
throw e;
} Prevention
- Serialize deletions of the same menu (e.g. optimistic locking or unique UI action).
- Make deletes idempotent: 0 affected rows on an already-deleted row is acceptable.
- Debounce/deduplicate retry requests from the client.
When it happens
Trigger: Calling deleteUacMenuById(id) where the row passed the initial existence check but was deleted concurrently by another transaction before deleteByPrimaryKey ran, or where the primary-key delete matched 0 rows for any reason.
Common situations: Two admins deleting the same menu simultaneously; duplicate delete requests from a retried HTTP call racing each other; read-replica/primary lag making the existence check pass on stale data.
Related errors
AI-assisted analysis of paascloud/paascloud-master@781281a950 (2026-09-10).
Data as JSON: /api/errors/dc48bb1d10b4ff78.
Report an issue: GitHub.
Appendix: source
Thrown at paascloud-provider/paascloud-provider-uac/src/main/java/com/paascloud/provider/service/impl/UacMenuServiceImpl.java:187
// 获取当前菜单信息
UacMenu uacMenuQuery = new UacMenu();
uacMenuQuery.setId(id);
uacMenuQuery = mapper.selectOne(uacMenuQuery);
if (PublicUtil.isEmpty(uacMenuQuery)) {
throw new UacBizException(ErrorCodeEnum.UAC10013003, id);
}
// 删除菜单与角色的关联关系
UacRoleMenu uacRoleMenu = new UacRoleMenu();
uacRoleMenu.setMenuId(id);
uacRoleMenuService.delete(uacRoleMenu);
// 删除菜单
result = uacMenuMapper.deleteByPrimaryKey(id);
if (result < 1) {
logger.error("删除菜单失败 menuId={}", id);
throw new UacBizException(ErrorCodeEnum.UAC10013008, id);
}
// 删除权限
// TODO 应该先查询再删除
uacActionService.deleteByMenuId(id);
// 修改当前删除菜单的父菜单是否是叶子节点
UacMenu updateParentUacMenu = new UacMenu();
updateParentUacMenu.setId(uacMenuQuery.getPid());
updateParentUacMenu.setLeaf(MenuConstant.MENU_LEAF_YES);
// 是二三级
if (Objects.equals(MenuConstant.MENU_LEVEL_TWO, uacMenuQuery.getLevel()) || Objects.equals(MenuConstant.MENU_LEVEL_THREE, uacMenuQuery.getLevel())) {
// 查询是否是叶子节点
int count = uacMenuMapper.selectMenuChildCountByPid(uacMenuQuery.getPid());
if (count == 0) {
uacMenuMapper.updateByPrimaryKeySelective(updateParentUacMenu);
}
}View on GitHub (pinned to 781281a950)