flipped-aurora/gin-vue-admin · error
sys_base_menus子菜单初始化失败!
Error message
sys_base_menus子菜单初始化失败!
What it means
Thrown by the menu initializer when inserting the second-level (child) seed menus into sys_base_menus fails. Child menus carry ParentId values resolved from menuNameMap built from the successfully inserted parent rows, so this error means the parent batch succeeded but the child batch's db.Create failed.
Source
Thrown at server/source/system/menu.go:144
// AI 工坊
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["ai"], Path: "mcpTool", Name: "mcpTool", Component: "plugin/ai/view/mcp/mcp.vue", Sort: 1, Meta: Meta{Title: "Mcp Tools模板", Icon: "grid"}},
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["ai"], Path: "mcpTest", Name: "mcpTest", Component: "plugin/ai/view/mcp/mcpTest.vue", Sort: 2, Meta: Meta{Title: "Mcp Tools管理", Icon: "connection"}},
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["ai"], Path: "mcpApi", Name: "McpApi", Component: "plugin/ai/view/mcpApi/index.vue", Sort: 3, Meta: Meta{Title: "AI MCP构建", Icon: "set-up"}},
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["ai"], Path: "skills", Name: "Skills", Component: "plugin/ai/view/skills/index.vue", Sort: 4, Meta: Meta{Title: "Skills管理", Icon: "edit-pen"}},
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["ai"], Path: "cli", Name: "Cli", Component: "plugin/ai/view/cli/index.vue", Sort: 5, Meta: Meta{Title: "AI CLI管理", Icon: "monitor", KeepAlive: true}},
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["ai"], Path: "picture", Name: "picture", Component: "plugin/ai/view/picture/picture.vue", Sort: 6, Meta: Meta{Title: "AI页面绘制", Icon: "picture"}},
// 插件系统
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["plugin"], Path: "https://plugin.gin-vue-admin.com/", Name: "https://plugin.gin-vue-admin.com/", Component: "https://plugin.gin-vue-admin.com/", Sort: 0, Meta: Meta{Title: "插件市场", Icon: "shop"}},
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["plugin"], Path: "installPlugin", Name: "installPlugin", Component: "view/systemTools/installPlugin/index.vue", Sort: 1, Meta: Meta{Title: "插件安装", Icon: "box"}},
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["plugin"], Path: "pubPlug", Name: "pubPlug", Component: "view/systemTools/pubPlug/pubPlug.vue", Sort: 3, Meta: Meta{Title: "打包插件", Icon: "suitcase"}},
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["plugin"], Path: "plugin-email", Name: "plugin-email", Component: "plugin/email/view/index.vue", Sort: 4, Meta: Meta{Title: "邮件插件", Icon: "message"}},
{MenuLevel: 1, Hidden: false, ParentId: menuNameMap["plugin"], Path: "anInfo", Name: "anInfo", Component: "plugin/announcement/view/info.vue", Sort: 5, Meta: Meta{Title: "公告管理[示例]", Icon: "bell"}},
}
// 创建子菜单
if err = db.Create(&childMenus).Error; err != nil {
return ctx, errors.Wrap(err, SysBaseMenu{}.TableName()+"子菜单初始化失败!")
}
// 组合所有菜单作为返回结果
allEntities := append(allMenus, childMenus...)
next = context.WithValue(ctx, i.InitializerName(), allEntities)
return next, nil
}
func (i *initMenu) DataInserted(ctx context.Context) bool {
db, ok := ctx.Value("db").(*gorm.DB)
if !ok {
return false
}
if errors.Is(db.Where("path = ?", "dashboard").First(&SysBaseMenu{}).Error, gorm.ErrRecordNotFound) { // 判断是否存在数据
return false
}
return true
}View on GitHub (pinned to 3136500ef3)
Solutions
- Inspect the wrapped GORM error (duplicate key vs constraint vs connection)
- Drop/TRUNCATE sys_base_menus so both parent and child phases re-run atomically against a clean table
- Ensure AutoMigrate of SysBaseMenu and SysBaseMenuParameter ran before init
- Only run initialization once per database (guard with DataInserted) and avoid concurrent init runs
- Check for pre-existing menus with colliding Path/Name and rename/remove them
Example fix
// before: partial seed leaves parents, child insert hits duplicate path
ctx, err = initMenu{}.InitializeData(ctx)
// after: clean slate then init
_ = db.Where("1 = 1").Delete(&system.SysBaseMenu{})
if err := db.AutoMigrate(&system.SysBaseMenu{}); err != nil { return err }
ctx, err = initMenu{}.InitializeData(ctx) Defensive patterns
Strategy: validation
Validate before calling
var count int64
if err := db.Model(&system.SysBaseMenu{}).Count(&count).Error; err != nil { return err }
if count > 0 { return nil } // skip full reseed, avoids partial parent/child state
if err := db.AutoMigrate(&system.SysBaseMenu{}); err != nil { return err } Type guard
func parentsSeeded(ctx context.Context) ([]system.SysBaseMenu, bool) {
menus, ok := ctx.Value(new(initMenu).InitializerName()).([]system.SysBaseMenu)
return menus, ok && len(menus) > 0
} Try / catch
ctx, err = initMenu{}.InitializeData(ctx)
if err != nil {
if strings.Contains(err.Error(), "子菜单初始化失败") {
log.Printf("child menu insert failed, check duplicate paths/parents: %v", errors.Cause(err))
}
return err
} Prevention
- Seed parents and children against a clean table so both phases are consistent
- Check for pre-existing menus with colliding Path/Name before init
- Run the initializer once, guarded by DataInserted
- Verify FK integrity so child ParentId values always resolve
When it happens
Trigger: db.Create(&childMenus) fails: missing table, duplicate path/name unique key from prior seeding, ParentId referencing a parent deleted between phases, constraint violations, or DB failure mid-insert.
Common situations: Partially completed init from a crashed previous run left parent rows but conflicting child rows; another admin inserted a menu with the same Path/Name; schema drift after upgrading gin-vue-admin added NOT NULL columns; DB connection dropped between the two Create batches.
Related errors
- sys_base_menus父级菜单初始化失败!
- media.FileUploadAndDownload表数据初始化失败!
- sys_apis表数据初始化失败!
- sys_ignore_apis表数据初始化失败!
- %s表数据初始化失败!
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/a2b27f0b6a7c06d6.
Report an issue: GitHub.