{"record":{"id":"e081ef346981b09b","repo":"flipped-aurora/gin-vue-admin","slug":"cli","errorCode":null,"errorMessage":"cli名称不能为空","messagePattern":"cli名称不能为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/plugin/ai/service/sys_cli.go","lineNumber":21,"sourceCode":"import (\n\t\"context\"\n\t\"errors\"\n\t\"strings\"\n\n\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}","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/plugin/ai/service/sys_cli.go#L3-L39","documentation":"CreateCli in the ai plugin creates a SysCli record. It trims req.Name and rejects an empty result with this error before any uniqueness check, because a CLI without a name cannot be identified or invoked. The empty-name guard is the first validation in the create flow.","triggerScenarios":"Calling CreateCli (via the ai plugin API or MCP tool) with CreateSysCliRequest.Name empty or whitespace-only — e.g. a form field left blank, or programmatic callers omitting name.","commonSituations":"Frontend CLI management form submitted without the name input; scripts/API consumers building the request without `name`; whitespace-only input from copy-paste that passes naive required checks.","solutions":["Provide a non-empty name in the request body: {\"name\":\"my-cli\", ...}","Make the name field required in the frontend form and validate before submit","Trim input on the client too so whitespace-only values are caught early","If calling programmatically, assert name is present before invoking the API"],"exampleFix":"// before\nawait createCli({ command: 'run', displayName: 'My CLI' })\n// after\nawait createCli({ name: 'my-cli', command: 'run', displayName: 'My CLI' })","handlingStrategy":"validation","validationCode":"// client-side\nconst name = String(req.name ?? '').trim()\nif (!name) throw new Error('name is required to create a CLI')","typeGuard":"function hasCliName(r) {\n  return typeof r?.name === 'string' && r.name.trim().length > 0\n}","tryCatchPattern":"try {\n  await createCli(req)\n} catch (e) {\n  if (String(e.message).includes('cli名称不能为空')) {\n    formRef.value.validateField('name')\n  } else { throw e }\n}","preventionTips":["Make the CLI name field required with form validation before submit","Trim the name client-side so whitespace-only values are rejected early","Include name in any programmatic CreateSysCliRequest construction"],"tags":["plugin","validation","ai-plugin"],"backgroundTag":"missing-required-field","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}