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

  1. Delete the child roles first (leaf-to-root order), then delete the parent.
  2. Re-parent the children to another role (update their parent_id), then delete the original parent.
  3. 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

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.