{"record":{"id":"60f4ea3b476e6da3","repo":"flipped-aurora/gin-vue-admin","slug":"cron-w","errorCode":null,"errorMessage":"cron 表达式非法: %w","messagePattern":"cron 表达式非法: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/sys_timed_task.go","lineNumber":39,"sourceCode":"// TimedTaskService 定时任务服务(全局单例 + global.GVA_DB, 遵项目既有约定)\ntype TimedTaskService struct{}\n\nvar TimedTaskServiceApp = new(TimedTaskService)\n\n// timedTaskCronName 一任务一 cronName: robfig/cron 无单任务 pause,\n// 启停语义 = Clear(cronName) + 按 DB 重加, 状态以 DB enabled 为准。\nfunc timedTaskCronName(id uint) string { return fmt.Sprintf(\"timedTask/%d\", id) }\n\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) {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_timed_task.go#L21-L57","documentation":"ValidateSpec checks a cron expression before persisting a timed task. It parses with a 6-field parser (seconds enabled) or cron.ParseStandard (5 fields) depending on withSeconds; a parse failure is wrapped as 'cron 表达式非法'. This follows robfig/cron semantics: field count and descriptors must match the chosen parser mode.","triggerScenarios":"Creating or updating a timed task whose Spec cannot be parsed: wrong number of fields for the withSeconds mode (e.g. 5 fields with withSeconds=true, or 6 fields with withSeconds=false), invalid field values (e.g. month 13), or misused descriptors.","commonSituations":"Pasting a 6-field quartz-style expression into a task configured with WithSeconds=false; using ranges like '0 0 * * * *' with standard 5-field parsing; typos such as '* * *' (missing fields); interval descriptors incompatible with the parser.","solutions":["Match field count to withSeconds: 5 fields when WithSeconds=false, 6 fields (with seconds first) when true","Validate the expression with the same library locally (cron.ParseStandard or cron.NewParser with Second flag) before submitting","Fix out-of-range values in any field (minute 0-59, hour 0-23, day-of-month 1-31, month 1-12, day-of-week 0-6)","Use descriptors like @daily/@hourly only if the selected parser supports them"],"exampleFix":"// before\n{ \"spec\": \"0 30 2 * * *\", \"withSeconds\": false } // 6 fields, standard parser -> invalid\n// after\n{ \"spec\": \"30 2 * * *\", \"withSeconds\": false }\n// or\n{ \"spec\": \"0 30 2 * * *\", \"withSeconds\": true }","handlingStrategy":"validation","validationCode":"// Go: pre-validate with the same parsers used by ValidateSpec\nfunc validCron(spec string, withSeconds bool) bool {\n    if withSeconds {\n        p := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)\n        _, err := p.Parse(spec)\n        return err == nil\n    }\n    _, err := cron.ParseStandard(spec)\n    return err == nil\n}","typeGuard":null,"tryCatchPattern":"err := svc.CreateTimedTask(task)\nif err != nil && strings.Contains(err.Error(), \"cron 表达式非法\") {\n    // fix the spec: 5 fields (standard) or 6 fields with seconds, then resubmit\n    return fmt.Errorf(\"请检查 cron 字段数与取值范围: %w\", err)\n}","preventionTips":["Use 5 fields for standard mode, 6 (seconds first) only when withSeconds=true","Test cron strings in the same library (robfig/cron) before submitting","Watch for quartz-style expressions silently pasted into a standard parser","Prefer named descriptors (@daily, @hourly) for simple schedules"],"tags":["cron","validation","go"],"backgroundTag":"invalid-cron-expression","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}