flipped-aurora/gin-vue-admin · error
不能将字典详情设置为自己或其子项的父级
Error message
不能将字典详情设置为自己或其子项的父级
What it means
UpdateSysDictionaryDetail rejects updates that would make a detail's parent be itself or one of its own descendants, which would create a cycle in the parent/child hierarchy. It uses checkCircularReference to walk the proposed parent's ancestry chain.
Source
Thrown at server/service/system/sys_dictionary_detail.go:84
//@author: [piexlmax](https://github.com/piexlmax)
//@function: UpdateSysDictionaryDetail
//@description: 更新字典详情数据
//@param: sysDictionaryDetail *model.SysDictionaryDetail
//@return: err error
func (dictionaryDetailService *DictionaryDetailService) UpdateSysDictionaryDetail(ctx context.Context, sysDictionaryDetail *system.SysDictionaryDetail) (err error) {
// 如果更新了父级ID,需要重新计算层级和路径
if sysDictionaryDetail.ParentID != nil {
var parent system.SysDictionaryDetail
err = global.GVA_DB.WithContext(ctx).First(&parent, *sysDictionaryDetail.ParentID).Error
if err != nil {
return err
}
// 检查循环引用
if dictionaryDetailService.checkCircularReference(ctx, sysDictionaryDetail.ID, *sysDictionaryDetail.ParentID) {
return fmt.Errorf("不能将字典详情设置为自己或其子项的父级")
}
sysDictionaryDetail.Level = parent.Level + 1
if parent.Path == "" {
sysDictionaryDetail.Path = strconv.Itoa(int(parent.ID))
} else {
sysDictionaryDetail.Path = parent.Path + "," + strconv.Itoa(int(parent.ID))
}
} else {
sysDictionaryDetail.Level = 0
sysDictionaryDetail.Path = ""
}
err = global.GVA_DB.WithContext(ctx).Save(sysDictionaryDetail).Error
if err != nil {
return err
}
View on GitHub (pinned to 3136500ef3)
Solutions
- Choose a ParentID outside the detail's own subtree
- Verify the proposed parent's Path does not start with the detail's Path before saving
- In UI, disable drop targets that are the node itself or its descendants
Example fix
// before
await updateDetail({ id: node.id, parentId: node.id }) // cycle
// after
const parent = await getDetail(proposedParentId)
if (!parent.path.startsWith(`${node.path}/`)) {
await updateDetail({ id: node.id, parentId: proposedParentId })
} Defensive patterns
Strategy: validation
Validate before calling
const target = detailMap[proposedParentId]
if (target.path.startsWith(`${node.path}/`)) {
throw new Error('cannot move node into its own subtree')
} Try / catch
try {
await updateDetail(payload)
} catch (e) {
if (e.message.includes('父级')) {
ElMessage.error('不能移动到自身或子节点')
}
} Prevention
- Use the tree component's built-in drop restrictions
- Keep node.path authoritative for hierarchy checks
When it happens
Trigger: Calling UpdateSysDictionaryDetail with a ParentID equal to the detail's own ID, or pointing at any detail whose ancestor chain contains the detail being updated.
Common situations: Bulk edits or drag-and-drop tree UIs moving a subtree under its own descendant; scripts re-parenting details without cycle checks; concurrent edits creating transient loops.
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/5d0b895e0b84fa9b.
Report an issue: GitHub.