{"record":{"id":"a2b27f0b6a7c06d6","repo":"flipped-aurora/gin-vue-admin","slug":"sys-base-menus-a2b27f","errorCode":null,"errorMessage":"sys_base_menus子菜单初始化失败!","messagePattern":"sys_base_menus子菜单初始化失败!","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/source/system/menu.go","lineNumber":144,"sourceCode":"\t\t// AI 工坊\n\t\t{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\"}},\n\t\t{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\"}},\n\t\t{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\"}},\n\t\t{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\"}},\n\t\t{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}},\n\t\t{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\"}},\n\n\t\t// 插件系统\n\t\t{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\"}},\n\t\t{MenuLevel: 1, Hidden: false, ParentId: menuNameMap[\"plugin\"], Path: \"installPlugin\", Name: \"installPlugin\", Component: \"view/systemTools/installPlugin/index.vue\", Sort: 1, Meta: Meta{Title: \"插件安装\", Icon: \"box\"}},\n\t\t{MenuLevel: 1, Hidden: false, ParentId: menuNameMap[\"plugin\"], Path: \"pubPlug\", Name: \"pubPlug\", Component: \"view/systemTools/pubPlug/pubPlug.vue\", Sort: 3, Meta: Meta{Title: \"打包插件\", Icon: \"suitcase\"}},\n\t\t{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\"}},\n\t\t{MenuLevel: 1, Hidden: false, ParentId: menuNameMap[\"plugin\"], Path: \"anInfo\", Name: \"anInfo\", Component: \"plugin/announcement/view/info.vue\", Sort: 5, Meta: Meta{Title: \"公告管理[示例]\", Icon: \"bell\"}},\n\t}\n\n\t// 创建子菜单\n\tif err = db.Create(&childMenus).Error; err != nil {\n\t\treturn ctx, errors.Wrap(err, SysBaseMenu{}.TableName()+\"子菜单初始化失败!\")\n\t}\n\n\t// 组合所有菜单作为返回结果\n\tallEntities := append(allMenus, childMenus...)\n\tnext = context.WithValue(ctx, i.InitializerName(), allEntities)\n\treturn next, nil\n}\n\nfunc (i *initMenu) DataInserted(ctx context.Context) bool {\n\tdb, ok := ctx.Value(\"db\").(*gorm.DB)\n\tif !ok {\n\t\treturn false\n\t}\n\tif errors.Is(db.Where(\"path = ?\", \"dashboard\").First(&SysBaseMenu{}).Error, gorm.ErrRecordNotFound) { // 判断是否存在数据\n\t\treturn false\n\t}\n\treturn true\n}","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/source/system/menu.go#L126-L162","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: partial seed leaves parents, child insert hits duplicate path\nctx, err = initMenu{}.InitializeData(ctx)\n// after: clean slate then init\n_ = db.Where(\"1 = 1\").Delete(&system.SysBaseMenu{})\nif err := db.AutoMigrate(&system.SysBaseMenu{}); err != nil { return err }\nctx, err = initMenu{}.InitializeData(ctx)","handlingStrategy":"validation","validationCode":"var count int64\nif err := db.Model(&system.SysBaseMenu{}).Count(&count).Error; err != nil { return err }\nif count > 0 { return nil } // skip full reseed, avoids partial parent/child state\nif err := db.AutoMigrate(&system.SysBaseMenu{}); err != nil { return err }","typeGuard":"func parentsSeeded(ctx context.Context) ([]system.SysBaseMenu, bool) {\n    menus, ok := ctx.Value(new(initMenu).InitializerName()).([]system.SysBaseMenu)\n    return menus, ok && len(menus) > 0\n}","tryCatchPattern":"ctx, err = initMenu{}.InitializeData(ctx)\nif err != nil {\n    if strings.Contains(err.Error(), \"子菜单初始化失败\") {\n        log.Printf(\"child menu insert failed, check duplicate paths/parents: %v\", errors.Cause(err))\n    }\n    return err\n}","preventionTips":["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"],"tags":["gorm","database","menu","seed-data","initialization"],"backgroundTag":"seed-data-insert-failed","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}