{"record":{"id":"b8fc9abb7df8cd4e","repo":"flipped-aurora/gin-vue-admin","slug":"sys-base-menus","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":73,"sourceCode":"\tallMenus := []SysBaseMenu{\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"dashboard\", Name: \"dashboard\", Component: \"view/dashboard/index.vue\", Sort: 1, Meta: Meta{Title: \"仪表盘\", Icon: \"odometer\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"permission\", Name: \"permission\", Component: \"view/routerHolder.vue\", Sort: 2, Meta: Meta{Title: \"权限管理\", Icon: \"perm-gva\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"org\", Name: \"org\", Component: \"view/routerHolder.vue\", Sort: 3, Meta: Meta{Title: \"组织管理\", Icon: \"share\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"systemConfig\", Name: \"systemConfig\", Component: \"view/routerHolder.vue\", Sort: 4, Meta: Meta{Title: \"系统设置\", Icon: \"config-gva\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"monitor\", Name: \"monitor\", Component: \"view/routerHolder.vue\", Sort: 5, Meta: Meta{Title: \"运维监控\", Icon: \"monitor-gva\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"media\", Name: \"media\", Component: \"view/routerHolder.vue\", Sort: 6, Meta: Meta{Title: \"媒体管理\", Icon: \"folder-opened\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"systemTools\", Name: \"systemTools\", Component: \"view/routerHolder.vue\", Sort: 7, Meta: Meta{Title: \"编程辅助\", Icon: \"cpu\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"ai\", Name: \"ai\", Component: \"view/routerHolder.vue\", Sort: 8, Meta: Meta{Title: \"AI 工坊\", Icon: \"ai-gva\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"example\", Name: \"example\", Component: \"view/example/index.vue\", Sort: 9, Meta: Meta{Title: \"示例文件\", Icon: \"example-gva\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"plugin\", Name: \"plugin\", Component: \"view/routerHolder.vue\", Sort: 10, Meta: Meta{Title: \"插件系统\", Icon: \"cherry\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"https://www.gin-vue-admin.com\", Name: \"https://www.gin-vue-admin.com\", Component: \"/\", Sort: 11, Meta: Meta{Title: \"官方网站\", Icon: \"customer-gva\"}},\n\t\t{MenuLevel: 0, Hidden: false, ParentId: 0, Path: \"about\", Name: \"about\", Component: \"view/about/index.vue\", Sort: 12, Meta: Meta{Title: \"关于我们\", Icon: \"office-building\"}},\n\t\t{MenuLevel: 0, Hidden: true, ParentId: 0, Path: \"person\", Name: \"person\", Component: \"view/person/person.vue\", Sort: 13, Meta: Meta{Title: \"个人信息\", Icon: \"postcard\"}},\n\t}\n\n\t// 先创建父级菜单（ParentId = 0 的菜单）\n\tif err = db.Create(&allMenus).Error; err != nil {\n\t\treturn ctx, errors.Wrap(err, SysBaseMenu{}.TableName()+\"父级菜单初始化失败!\")\n\t}\n\n\t// 建立菜单映射 - 通过Name查找已创建的菜单及其ID\n\tmenuNameMap := make(map[string]uint)\n\tfor _, menu := range allMenus {\n\t\tmenuNameMap[menu.Name] = menu.ID\n\t}\n\n\t// 定义子菜单，并设置正确的ParentId\n\tchildMenus := []SysBaseMenu{\n\t\t// 权限管理\n\t\t{MenuLevel: 1, Hidden: false, ParentId: menuNameMap[\"permission\"], Path: \"authority\", Name: \"authority\", Component: \"view/superAdmin/authority/authority.vue\", Sort: 1, Meta: Meta{Title: \"角色管理\", Icon: \"role-gva\"}},\n\t\t{MenuLevel: 1, Hidden: false, ParentId: menuNameMap[\"permission\"], Path: \"menu\", Name: \"menu\", Component: \"view/superAdmin/menu/menu.vue\", Sort: 2, Meta: Meta{Title: \"菜单管理\", Icon: \"tickets\", KeepAlive: true}},\n\t\t{MenuLevel: 1, Hidden: false, ParentId: menuNameMap[\"permission\"], Path: \"api\", Name: \"api\", Component: \"view/superAdmin/api/api.vue\", Sort: 3, Meta: Meta{Title: \"api管理\", Icon: \"api-gva\", KeepAlive: true}},\n\t\t{MenuLevel: 1, Hidden: false, ParentId: menuNameMap[\"permission\"], Path: \"apiToken\", Name: \"apiToken\", Component: \"view/systemTools/apiToken/index.vue\", Sort: 4, Meta: Meta{Title: \"API Token\", Icon: \"key\"}},\n\n\t\t// 组织管理\n\t\t{MenuLevel: 1, Hidden: false, ParentId: menuNameMap[\"org\"], Path: \"user\", Name: \"user\", Component: \"view/superAdmin/user/user.vue\", Sort: 1, Meta: Meta{Title: \"用户管理\", Icon: \"user\"}},","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/source/system/menu.go#L55-L91","documentation":"Thrown by the menu initializer (initMenu.InitializeData) when the batch insert of the top-level (ParentId=0) seed menus into sys_base_menus fails. The error wraps the GORM error and names the table plus the phase (父级菜单), distinguishing it from the later child-menu insert failure.","triggerScenarios":"db.Create(&allMenus) fails: sys_base_menus table not migrated, duplicate unique key (path/name) from a previous partial init, constraint violation on menu columns, or DB connectivity loss during insert.","commonSituations":"Re-running initialization on an already-seeded database (duplicate menu Name/Path); partially created menus from an earlier crashed init; model column mismatch after version upgrade changed the menu schema; DB in read-only mode during deploy.","solutions":["Inspect the wrapped GORM error for the exact SQL failure (duplicate key, missing table, etc.)","AutoMigrate SysBaseMenu (and related casbin/menu models) before running the menu initializer","Clear sys_base_menus (or the whole DB) and re-run initialization so seed inserts start clean","Run initialization only once — guard with DataInserted(ctx) / the init flag in system config","Verify DB credentials and writability before invoking the init flow"],"exampleFix":"// before: re-running init on seeded DB duplicates menus\nctx, err = initMenu{}.InitializeData(ctx)\n// after: only init when not already inserted\nif !(initMenu{}).DataInserted(ctx) {\n    if err := db.AutoMigrate(&system.SysBaseMenu{}); err != nil { return err }\n    ctx, err = initMenu{}.InitializeData(ctx)\n}","handlingStrategy":"validation","validationCode":"if !db.Migrator().HasTable(&system.SysBaseMenu{}) {\n    if err := db.AutoMigrate(&system.SysBaseMenu{}); err != nil { return err }\n}\nvar count int64\nif err := db.Model(&system.SysBaseMenu{}).Count(&count).Error; err != nil { return err }\nif count > 0 { return nil } // menus already seeded","typeGuard":"func hasDB(ctx context.Context) (*gorm.DB, bool) {\n    db, ok := ctx.Value(\"db\").(*gorm.DB)\n    return db, ok && db != nil\n}","tryCatchPattern":"ctx, err = initMenu{}.InitializeData(ctx)\nif err != nil {\n    log.Printf(\"menu seed failed: %v (cause: %v)\", err, errors.Cause(err))\n    return err\n}","preventionTips":["Use the system init flag so menu seeding runs only on a fresh DB","AutoMigrate menu models before init","Truncate menu tables before re-running init to avoid unique Path/Name conflicts","Never run initializers concurrently against the same database"],"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"}