{"record":{"id":"5d15998801337c52","repo":"flipped-aurora/gin-vue-admin","slug":"error-5d1599","errorCode":null,"errorMessage":"任务名不能为空","messagePattern":"任务名不能为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/sys_timed_task.go","lineNumber":47,"sourceCode":"\n// ValidateSpec 服务端校验 cron 表达式(含 @daily/@hourly 等描述符)\nfunc (s *TimedTaskService) ValidateSpec(spec string, withSeconds bool) error {\n\tvar err error\n\tif withSeconds {\n\t\t_, err = cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor).Parse(spec)\n\t} else {\n\t\t_, err = cron.ParseStandard(spec)\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cron 表达式非法: %w\", err)\n\t}\n\treturn nil\n}\n\n// validateTask 落库前统一校验(创建/更新共用)\nfunc (s *TimedTaskService) validateTask(t *system.SysTimedTask) error {\n\tif t.Name == \"\" {\n\t\treturn errors.New(\"任务名不能为空\")\n\t}\n\tif err := s.ValidateSpec(t.Spec, t.WithSeconds); err != nil {\n\t\treturn err\n\t}\n\tswitch t.ExecutorType {\n\tcase system.TimedTaskExecutorMethod:\n\t\tif _, ok := task.Get(t.MethodName); !ok {\n\t\t\treturn fmt.Errorf(\"方法 %s 未注册\", t.MethodName)\n\t\t}\n\t\tif len(t.Params) > 0 && !json.Valid(t.Params) {\n\t\t\treturn errors.New(\"params 必须是合法 JSON\")\n\t\t}\n\tcase system.TimedTaskExecutorHTTP:\n\t\tu, err := url.Parse(t.HttpUrl)\n\t\tif err != nil || (u.Scheme != \"http\" && u.Scheme != \"https\") || u.Host == \"\" {\n\t\t\treturn errors.New(\"httpUrl 必须是合法的 http/https 地址\")\n\t\t}\n\t\tif len(t.HttpHeader) > 0 {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_timed_task.go#L29-L65","documentation":"validateTask in TimedTaskService performs pre-persist validation shared by CreateTimedTask and UpdateTimedTask. It throws \"任务名不能为空\" when SysTimedTask.Name is the empty string, because the task name is required for uniqueness checks and display.","triggerScenarios":"POST/PUT to the timed-task API with a body missing \"name\" or with name:\"\"; programmatically constructing SysTimedTask without setting Name before CreateTimedTask/UpdateTimedTask.","commonSituations":"Frontend form submitted with only cron/spec filled; API clients using partial update payloads where name is omitted; JSON field name mismatch (e.g. \"taskName\") so Name decodes to empty.","solutions":["Include a non-empty \"name\" field in the create/update request payload.","Validate name in the frontend form as required before submitting.","Verify the JSON binding tags match the client's field names so Name is actually populated."],"exampleFix":"// before\nsvc.CreateTimedTask(ctx, &system.SysTimedTask{Spec: \"*/5 * * * *\"})\n\n// after\nsvc.CreateTimedTask(ctx, &system.SysTimedTask{Name: \"cleanup-logs\", Spec: \"*/5 * * * *\"})","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(task.Name) == \"\" {\n    return errors.New(\"任务名不能为空\")\n}\n// proceed with svc.CreateTimedTask / svc.UpdateTimedTask","typeGuard":"func hasName(t system.SysTimedTask) bool { return strings.TrimSpace(t.Name) != \"\" }","tryCatchPattern":"if err := svc.CreateTimedTask(ctx, task); err != nil {\n    if strings.Contains(err.Error(), \"任务名不能为空\") {\n        http.Error(w, \"name is required\", http.StatusBadRequest)\n        return\n    }\n    http.Error(w, err.Error(), http.StatusInternalServerError)\n}","preventionTips":["Mark the name field required in the frontend form","Verify JSON field names match binding tags","Validate payloads before API calls","Send full objects on update, not sparse maps"],"tags":["validation","go","scheduled-task"],"backgroundTag":"required-field-missing","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}