{"record":{"id":"7103cc1ab8d0bc93","repo":"Billionmail/BillionMail","slug":"threads-must-be-greater-than-zero","errorCode":null,"errorMessage":"threads must be greater than zero","messagePattern":"threads must be greater than zero","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/batch_mail/task_executor.go","lineNumber":1461,"sourceCode":"\tif total > 0 {\n\t\tsuccessRate = float64(sent) / float64(total)\n\t}\n\n\treturn map[string]interface{}{\n\t\t\"sent_count\":    sent,\n\t\t\"failed_count\":  failed,\n\t\t\"total_count\":   total,\n\t\t\"success_rate\":  successRate,\n\t\t\"current_speed\": e.rateController.GetCurrentRate(),\n\t\t\"max_rate\":      e.rateController.GetMaxRate(),\n\t\t\"duration_sec\":  duration,\n\t}\n}\n\nfunc (e *TaskExecutor) UpdateTaskThreads(taskId int, threads int) error {\n\t// parameter validation\n\tif threads <= 0 {\n\t\treturn fmt.Errorf(\"threads must be greater than zero\")\n\t}\n\n\tif threads > 100 {\n\t\treturn fmt.Errorf(\"threads must be less than 100\")\n\t}\n\n\t// get task info\n\ttask, err := GetTaskInfo(context.Background(), taskId)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get task info failed: %w\", err)\n\t}\n\n\tif task == nil || task.Id == 0 {\n\t\treturn fmt.Errorf(\"task %d not found\", taskId)\n\t}\n\n\t// record current pool status\n\tvar oldPoolSize int","sourceCodeStart":1443,"sourceCodeEnd":1479,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/batch_mail/task_executor.go#L1443-L1479","documentation":"UpdateTaskThreads validates the requested worker-thread count before touching the task. A threads value of zero or negative is rejected with this error, since a worker pool cannot run with no threads. It is the first guard in the function, before task lookup or pool resizing.","triggerScenarios":"Calling UpdateTaskThreads(taskId, 0) or with any negative value, typically from an HTTP handler bound to a request body where threads was omitted (zero value) or supplied as a negative number.","commonSituations":"API clients posting JSON without the threads field (Go decodes it as 0); UI sliders allowing 0; manual curl tests with negative numbers.","solutions":["Pass a threads value of 1-100.","Mark the threads field required in the API request schema and reject missing values at the handler.","Clamp/validate user input in the UI to a minimum of 1 before calling the endpoint."],"exampleFix":"// before: field omitted in request\n{\"taskId\": 42}\n// after\n{\"taskId\": 42, \"threads\": 10}","handlingStrategy":"validation","validationCode":"// Go\nif threads <= 0 {\n    return fmt.Errorf(\"threads must be in [1,100], got %d\", threads)\n}","typeGuard":"// TypeScript (client)\nfunction isValidThreads(n: unknown): n is number {\n  return typeof n === 'number' && Number.isInteger(n) && n >= 1 && n <= 100\n}","tryCatchPattern":"if err := executor.UpdateTaskThreads(taskId, threads); err != nil {\n    if strings.Contains(err.Error(), \"threads must be\") {\n        return gerror.Newf(gerror.CodeInvalidParameter, \"invalid threads %d: %v\", threads, err)\n    }\n    return err\n}","preventionTips":["Make threads a required field in the request DTO so omission fails binding, not silently as 0.","Validate 1 <= threads <= 100 at the API boundary and in the UI input.","Never pass raw user input straight into UpdateTaskThreads."],"tags":["validation","concurrency","batch-mail"],"backgroundTag":"parameter-validation-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}