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
- Verify the parentId exists (refresh the department tree in the frontend and re-submit)
- If creating a top-level department, send parentId=0 instead of a stale ID
- Check data-permission filters aren't hiding the parent row for the current user
- 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
- Refresh the department tree before submitting parent selection
- Exclude deleted parents from frontend dropdown options
- Send parentId=0 for top-level departments instead of stale IDs
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.