{"record":{"id":"1701a2ba0b5bf7bb","repo":"flipped-aurora/gin-vue-admin","slug":"w-name-s-path-s-component-s-path-s","errorCode":null,"errorMessage":"%w: name=%s, 已存在 path=%s component=%s, 期望 path=%s component=%s","messagePattern":"%w: name=(.+?), 已存在 path=(.+?) component=(.+?), 期望 path=(.+?) component=(.+?)","errorType":"exception","errorClass":"errAutoCodeMenuConflict","httpStatus":null,"severity":"error","filePath":"server/service/system/auto_code_persistence.go","lineNumber":81,"sourceCode":"\treturn nil\n}\n\nfunc persistAutoCodeMenu(\n\ttx *gorm.DB,\n\tinfo request.AutoCode,\n\tpackageTemplate string,\n\thistory *request.SysAutoHistoryCreate,\n) error {\n\tif !info.AutoCreateMenuToSql {\n\t\treturn nil\n\t}\n\tdesired := info.Menu(packageTemplate)\n\tvar existing model.SysBaseMenu\n\terr := tx.Where(\"name = ?\", desired.Name).First(&existing).Error\n\tswitch {\n\tcase err == nil:\n\t\tif existing.Name != desired.Name || existing.Path != desired.Path || existing.Component != desired.Component {\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"%w: name=%s, 已存在 path=%s component=%s, 期望 path=%s component=%s\",\n\t\t\t\terrAutoCodeMenuConflict,\n\t\t\t\tdesired.Name,\n\t\t\t\texisting.Path,\n\t\t\t\texisting.Component,\n\t\t\t\tdesired.Path,\n\t\t\t\tdesired.Component,\n\t\t\t)\n\t\t}\n\t\thistory.MenuID = existing.ID\n\t\treturn nil\n\tcase !errors.Is(err, gorm.ErrRecordNotFound):\n\t\treturn fmt.Errorf(\"查询自动代码菜单 %s 失败: %w\", desired.Name, err)\n\t}\n\n\tif info.AutoCreateBtnAuth && !info.OnlyTemplate {\n\t\tdesired.MenuBtn = []model.SysBaseMenuBtn{\n\t\t\t{Name: \"add\", Desc: \"新增\"},","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/auto_code_persistence.go#L63-L99","documentation":"This error is returned by persistAutoCodeMenu in server/service/system/auto_code_persistence.go when a sys_base_menu row with the same name already exists but its path or component differs from the menu the auto-code flow wants to persist. It wraps the sentinel errAutoCodeMenuConflict with a detailed diff (existing vs desired path/component) and fails the transaction, preventing an ambiguous silent overwrite of an existing menu definition.","triggerScenarios":"Generating/persisting auto-code whose desired menu name collides with an existing menu registered under a different path or component — e.g. re-running generation after changing packageTemplate, moving a generated page to another directory (component path changed), or a hand-created/edited menu sharing the auto-generated name.","commonSituations":"Developer renamed a package/router but kept the old menu name; two codegen runs produced different component paths under the same menu name; a previously generated menu was manually edited in the menu manager and now conflicts with regeneration; leftover menus from earlier codegen attempts.","solutions":["Read the message fields (existing path/component vs desired path/component) and decide which definition is correct.","Delete or rename the conflicting sys_base_menu entry in the menu manager, then re-run auto-code generation.","If the existing menu is intended, align the packageTemplate/menu config so the desired path/component matches the existing row.","If regeneration should win, back up and remove the old menu (and its children/parameters) before re-running.","Handle errAutoCodeMenuConflict distinctly in the caller (errors.Is) to surface the conflict details to the user instead of a generic failure."],"exampleFix":"// before\n// conflict: existing menu 'user' path='user' component='view/user/user.vue',\n// desired component changed to 'view/user/newUser.vue' -> generation aborts\n\n// after (resolve conflict, then regenerate)\n// In 系统管理 -> 菜单管理: rename or delete the conflicting 'user' menu,\n// then re-run auto-code generation so persistAutoCodeMenu creates the menu\n// with the new path/component without triggering errAutoCodeMenuConflict.","handlingStrategy":"validation","validationCode":"func menuConflict(db *gorm.DB, name, path, component string) error {\n    var m system.SysBaseMenu\n    err := db.Where(\"name = ?\", name).First(&m).Error\n    if errors.Is(err, gorm.ErrRecordNotFound) {\n        return nil\n    }\n    if err != nil {\n        return err\n    }\n    if m.Path != path || m.Component != component {\n        return fmt.Errorf(\"menu %q exists with path=%s component=%s, want path=%s component=%s\",\n            name, m.Path, m.Component, path, component)\n    }\n    return nil\n}\n// call before triggering auto-code generation/persistence\n","typeGuard":null,"tryCatchPattern":"err := svc.CreateAutoCodeHistory(info)\nif err != nil {\n    if errors.Is(err, errAutoCodeMenuConflict) {\n        return fmt.Errorf(\"menu conflict: rename/delete the existing menu or align packageTemplate, then regenerate\")\n    }\n    return err\n}","preventionTips":["Before regenerating a package, check sys_base_menu for menus with the same name and compare path/component.","Avoid manually editing auto-generated menus; treat them as generated artifacts managed by codegen.","When renaming a package/router, also rename or remove its old menu to avoid name collisions.","Use a stable menu naming convention derived from the package so regenerated names don't collide.","Handle errAutoCodeMenuConflict explicitly in the API layer to show the existing-vs-desired diff to the user."],"tags":["menu","conflict","persistence","auto-code","duplicate"],"backgroundTag":"menu-name-conflict","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}