Billionmail/BillionMail · error

threads must be greater than zero

Error message

threads must be greater than zero

What it means

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.

Source

Thrown at core/internal/service/batch_mail/task_executor.go:1461

	if total > 0 {
		successRate = float64(sent) / float64(total)
	}

	return map[string]interface{}{
		"sent_count":    sent,
		"failed_count":  failed,
		"total_count":   total,
		"success_rate":  successRate,
		"current_speed": e.rateController.GetCurrentRate(),
		"max_rate":      e.rateController.GetMaxRate(),
		"duration_sec":  duration,
	}
}

func (e *TaskExecutor) UpdateTaskThreads(taskId int, threads int) error {
	// parameter validation
	if threads <= 0 {
		return fmt.Errorf("threads must be greater than zero")
	}

	if threads > 100 {
		return fmt.Errorf("threads must be less than 100")
	}

	// get task info
	task, err := GetTaskInfo(context.Background(), taskId)
	if err != nil {
		return fmt.Errorf("get task info failed: %w", err)
	}

	if task == nil || task.Id == 0 {
		return fmt.Errorf("task %d not found", taskId)
	}

	// record current pool status
	var oldPoolSize int

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Pass a threads value of 1-100.
  2. Mark the threads field required in the API request schema and reject missing values at the handler.
  3. Clamp/validate user input in the UI to a minimum of 1 before calling the endpoint.

Example fix

// before: field omitted in request
{"taskId": 42}
// after
{"taskId": 42, "threads": 10}
Defensive patterns

Strategy: validation

Validate before calling

// Go
if threads <= 0 {
    return fmt.Errorf("threads must be in [1,100], got %d", threads)
}

Type guard

// TypeScript (client)
function isValidThreads(n: unknown): n is number {
  return typeof n === 'number' && Number.isInteger(n) && n >= 1 && n <= 100
}

Try / catch

if err := executor.UpdateTaskThreads(taskId, threads); err != nil {
    if strings.Contains(err.Error(), "threads must be") {
        return gerror.Newf(gerror.CodeInvalidParameter, "invalid threads %d: %v", threads, err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: API clients posting JSON without the threads field (Go decodes it as 0); UI sliders allowing 0; manual curl tests with negative numbers.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/7103cc1ab8d0bc93. Report an issue: GitHub.