flipped-aurora/gin-vue-admin · warning
此角色存在子角色不允许删除
Error message
此角色存在子角色不允许删除
What it means
DeleteAuthority blocks deletion of any role that still has child roles. It queries sys_authorities for a row with parent_id equal to the target's authority_id; if one exists, it returns "此角色存在子角色不允许删除". This preserves the role tree's integrity — parents cannot be removed while children point at them.
Source
Thrown at server/service/system/sys_authority.go:145
//@author: [piexlmax](https://github.com/piexlmax)
//@function: DeleteAuthority
//@description: 删除角色
//@param: auth *model.SysAuthority
//@return: err error
func (authorityService *AuthorityService) DeleteAuthority(ctx context.Context, auth *system.SysAuthority) error {
if errors.Is(global.GVA_DB.WithContext(ctx).Preload("Users").First(&auth).Error, gorm.ErrRecordNotFound) {
return errors.New("该角色不存在")
}
if len(auth.Users) != 0 {
return errors.New("此角色有用户正在使用禁止删除")
}
if !errors.Is(global.GVA_DB.WithContext(ctx).Where("authority_id = ?", auth.AuthorityId).First(&system.SysUser{}).Error, gorm.ErrRecordNotFound) {
return errors.New("此角色有用户正在使用禁止删除")
}
if !errors.Is(global.GVA_DB.WithContext(ctx).Where("parent_id = ?", auth.AuthorityId).First(&system.SysAuthority{}).Error, gorm.ErrRecordNotFound) {
return errors.New("此角色存在子角色不允许删除")
}
return global.GVA_DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
var err error
if err = tx.Preload("SysBaseMenus").Where("authority_id = ?", auth.AuthorityId).First(auth).Unscoped().Delete(auth).Error; err != nil {
return err
}
if len(auth.SysBaseMenus) > 0 {
if err = tx.Model(auth).Association("SysBaseMenus").Delete(auth.SysBaseMenus); err != nil {
return err
}
// err = db.Association("SysBaseMenus").Delete(&auth)
}
if err = tx.Delete(&system.SysUserAuthority{}, "sys_authority_authority_id = ?", auth.AuthorityId).Error; err != nil {
return err
}View on GitHub (pinned to 3136500ef3)
Solutions
- Delete the child roles first (leaf-to-root order), then delete the parent.
- Re-parent the children to another role (update their parent_id), then delete the original parent.
- Locate the blockers with: SELECT authority_id, authority_name FROM sys_authorities WHERE parent_id = <role>;
Example fix
// before
deleteAuthority({ authorityId: 888 }) // child 8881 exists
// after
deleteAuthority({ authorityId: 8881 }) // child first
deleteAuthority({ authorityId: 888 }) // then parent Defensive patterns
Strategy: validation
Validate before calling
const children = (await getAuthorityList()).data.list.filter(r => r.parentId === id)
if (children.length > 0) throw new Error('存在子角色:' + children.map(c => c.authorityId).join(', ') + ',请先删除子角色') Try / catch
try {
await deleteAuthority({ authorityId: id })
} catch (e) {
if (String(e?.msg).includes('此角色存在子角色不允许删除')) {
ElMessage.warning('请先删除或转移该角色的子角色')
} else { throw e }
} Prevention
- Delete role trees leaf-first (children before parents).
- Before deleting, query children: SELECT authority_id FROM sys_authorities WHERE parent_id = <role>.
- When flattening a hierarchy, explicitly re-parent or remove every child.
- After imports, validate parent_id values all point at roles you intend to keep.
When it happens
Trigger: DELETE /authority/deleteAuthority on a parent role that still has at least one child (parent_id referencing it in sys_authorities).
Common situations: Flattening a role hierarchy from the leaf up but missing a hidden/duplicated child; data imported with parent_id values pointing at roles assumed deleted; attempts to delete an intermediate role like 888 when 8881 is still its child.
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/cb51c62e0ad8d4bc.
Report an issue: GitHub.