flipped-aurora/gin-vue-admin · error

父部门不存在

Error message

父部门不存在

What it means

buildAncestors looks up the parent department to compose the ancestor ID chain for a new/updated department. When the given parentId does not exist in sys_department, GORM returns record-not-found and the service replaces it with this clearer error. It prevents creating departments pointing at non-existent parents.

Source

Thrown at server/service/system/sys_department.go:25

	"strings"

	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system"
	"gorm.io/gorm"
)

type SysDepartmentService struct{}

var SysDepartmentServiceApp = new(SysDepartmentService)

// buildAncestors 依据父部门推算祖级链: 顶级为 "0", 子级为 父.Ancestors + "," + 父ID
func (s *SysDepartmentService) buildAncestors(ctx context.Context, parentId uint) (string, error) {
	if parentId == 0 {
		return "0", nil
	}
	var parent system.SysDepartment
	if err := global.GVA_DB.WithContext(ctx).First(&parent, parentId).Error; err != nil {
		return "", errors.New("父部门不存在")
	}
	return parent.Ancestors + "," + strconv.Itoa(int(parent.ID)), nil
}

// buildDepartmentNamePath 依据部门自身与 id→name 映射, 拼出 "公司/部门" 全路径名(纯函数)
// dept.Ancestors 为祖级 ID 链(顶级 "0"、不含自身, 如 "0,1,5"); "0" 与映射中缺失的祖级会被跳过
func buildDepartmentNamePath(dept system.SysDepartment, nameByID map[uint]string) string {
	var parts []string
	for _, seg := range strings.Split(dept.Ancestors, ",") {
		seg = strings.TrimSpace(seg)
		if seg == "" || seg == "0" {
			continue
		}
		id, err := strconv.ParseUint(seg, 10, 64)
		if err != nil {
			continue
		}
		if name := nameByID[uint(id)]; name != "" {

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Verify the parentId exists (refresh the department tree in the frontend and re-submit)
  2. If creating a top-level department, send parentId=0 instead of a stale ID
  3. Check data-permission filters aren't hiding the parent row for the current user
  4. Wrap parent+child creation in one transaction to avoid the parent disappearing mid-operation

Example fix

// before
await createDepartment({ name: 'B', parentId: oldId })
// after
const parent = await getDepartment(oldId)
if (!parent) throw new Error('parent missing; refresh tree')
await createDepartment({ name: 'B', parentId: parent.ID })
Defensive patterns

Strategy: validation

Validate before calling

var count int64
global.GVA_DB.Model(&system.SysDepartment{}).Where("id = ?", parentId).Count(&count)
if parentId != 0 && count == 0 {
    return errors.New("parent department does not exist")
}

Try / catch

if err := deptService.CreateSysDepartment(ctx, dept); err != nil {
    if err.Error() == "父部门不存在" {
        // refresh tree data and ask user to reselect parent
    }
    return err
}

Prevention

When it happens

Trigger: CreateSysDepartment or UpdateSysDepartment called with a ParentId that is non-zero and not present in the database (e.g. parent deleted concurrently, wrong ID, stale form data).

Common situations: Client submitted a department form where the parent was deleted by another user; API consumer passing parentId of another tenant/dept scope filtered out by data permissions; seeded data referencing deleted IDs.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/d62b04b038d2f600. Report an issue: GitHub.