{"record":{"id":"5134e59b15cf1a43","repo":"flipped-aurora/gin-vue-admin","slug":"cli-5134e5","errorCode":null,"errorMessage":"存在同名CLI","messagePattern":"存在同名CLI","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/plugin/ai/service/sys_cli.go","lineNumber":26,"sourceCode":"\t\"github.com/flipped-aurora/gin-vue-admin/server/global\"\n\tsysModel \"github.com/flipped-aurora/gin-vue-admin/server/model/system\"\n\tautoModel \"github.com/flipped-aurora/gin-vue-admin/server/plugin/ai/model\"\n\tautoReq \"github.com/flipped-aurora/gin-vue-admin/server/plugin/ai/model/request\"\n\tautoRes \"github.com/flipped-aurora/gin-vue-admin/server/plugin/ai/model/response\"\n\t\"gorm.io/gorm\"\n)\n\ntype cliService struct{}\n\nfunc (s *cliService) CreateCli(ctx context.Context, req autoReq.CreateSysCliRequest) (autoModel.SysCli, error) {\n\tname := strings.TrimSpace(req.Name)\n\tif name == \"\" {\n\t\treturn autoModel.SysCli{}, errors.New(\"cli名称不能为空\")\n\t}\n\tif exists, err := s.sysCliNameExists(ctx, name, 0); err != nil {\n\t\treturn autoModel.SysCli{}, err\n\t} else if exists {\n\t\treturn autoModel.SysCli{}, errors.New(\"存在同名CLI\")\n\t}\n\tentity := autoModel.SysCli{\n\t\tName:             name,\n\t\tCommand:          strings.TrimSpace(req.Command),\n\t\tDisplayName:      strings.TrimSpace(req.DisplayName),\n\t\tVersion:          strings.TrimSpace(req.Version),\n\t\tDescription:      strings.TrimSpace(req.Description),\n\t\tStatus:           strings.TrimSpace(req.Status),\n\t\tAuthMode:         \"jwt\",\n\t\tSkillName:        strings.TrimSpace(req.SkillName),\n\t\tSkillDescription: strings.TrimSpace(req.SkillDescription),\n\t\tScenariosJSON:    req.ScenariosJSON, // JSON 原文不裁剪\n\t}\n\tapplySysCliDefaults(&entity)\n\tif err := global.GVA_DB.WithContext(ctx).Create(&entity).Error; err != nil {\n\t\treturn autoModel.SysCli{}, err\n\t}\n\treturn entity, nil","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/plugin/ai/service/sys_cli.go#L8-L44","documentation":"CreateCli enforces unique CLI names: after the empty check it calls sysCliNameExists(ctx, name, 0), where 0 means \"exclude no id\" (full-table uniqueness for creation). If a record with the same trimmed name already exists, creation is rejected with this error. This prevents duplicate CLI identifiers that would be ambiguous to invoke.","triggerScenarios":"Calling CreateCli with a name that already exists in the sys_cli table — e.g. resubmitting a form after a successful create, or two users/sessions creating the same CLI concurrently.","commonSituations":"Double-click/double-submit of the create form; importing or seeding CLIs that already exist; trying to \"update\" via the create endpoint; case or whitespace differences that trim to the same name.","solutions":["Use the update/edit endpoint for the existing CLI instead of creating a new one","Choose a different, unique name for the new CLI","Check the CLI list first to confirm whether the record already exists before creating","Disable the submit button after first click to avoid duplicate submissions"],"exampleFix":"// before: create on every save\nawait createCli({ name: 'my-cli' })\n// after: update when the record exists\nif (existingCliId) {\n  await updateCli(existingCliId, { name: 'my-cli' })\n} else {\n  await createCli({ name: 'my-cli' })\n}","handlingStrategy":"validation","validationCode":"// before create, check uniqueness client-side when the list is available\nif (cliList.some(c => c.name === name.trim())) {\n  throw new Error(`CLI \"${name}\" already exists — use update instead`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await createCli({ name })\n} catch (e) {\n  if (String(e.message).includes('存在同名CLI')) {\n    // switch the dialog to edit mode for the existing record\n    openEditForExisting(name)\n  } else { throw e }\n}","preventionTips":["Search the existing CLI list before creating to avoid duplicates","Debounce/disable the submit button to prevent double submissions","Use the update endpoint to modify existing CLIs, not create","Document that names are unique (post-trim) so users pick distinct names"],"tags":["plugin","uniqueness","duplicate-record"],"backgroundTag":"duplicate-resource-conflict","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}