Billionmail/BillionMail · error

get task info failed: %w

Error message

get task info failed: %w

What it means

After validating the thread count, UpdateTaskThreads loads the task via GetTaskInfo; if that lookup fails, the underlying error is wrapped with fmt.Errorf %w and returned as "get task info failed: <cause>". It indicates the task could not be fetched from the database/cache, and the root cause is preserved for errors.Is/As inspection.

Source

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

		"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
	var runningWorkers int
	if e.pool != nil {
		oldPoolSize = e.pool.Cap()
		runningWorkers = e.pool.Running()
	}

	// new threads
	newThreads := threads
	// calculate new rate limit - 20 emails per thread per second
	targetSendPerThreadPerSecond := 20

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Read the wrapped cause (%w) via errors.Is/As or the error string to identify the root failure.
  2. Check database connectivity and credentials (psql/health check, docker logs for the postgres container).
  3. Retry the operation once the DB is reachable; add retry with backoff for transient connection errors.
  4. Verify GetTaskInfo's query/table state if the cause is a SQL error.

Example fix

// before: opaque handling
if err := e.UpdateTaskThreads(id, n); err != nil { log.Print(err) }
// after
if err := e.UpdateTaskThreads(id, n); err != nil {
    var dbErr *pgconn.ConnectError
    if errors.As(err, &dbErr) { /* alert on DB connectivity */ }
    log.Printf("update threads: %v", err)
}
Defensive patterns

Strategy: retry

Validate before calling

// Go: verify DB reachability before the operation
if err := g.DB().PingMaster(); err != nil {
    return fmt.Errorf("db unavailable: %w", err)
}

Type guard

func isDBConnectErr(err error) bool {
    var netErr net.Error
    return errors.As(err, &netErr) || strings.Contains(err.Error(), "connect: ")
}

Try / catch

err := executor.UpdateTaskThreads(taskId, threads)
for i := 0; i < 3 && isDBConnectErr(err); i++ {
    time.Sleep(time.Second << i)
    err = executor.UpdateTaskThreads(taskId, threads)
}
if err != nil { log.Printf("get task info failed: %v", err) }

Prevention

When it happens

Trigger: Calling UpdateTaskThreads while the database is unreachable, the task table query errors (connection refused, timeout, locked table), or GetTaskInfo's context is cancelled.

Common situations: PostgreSQL down or restarting during the call; network partition between app and DB; connection pool exhausted under load; misconfigured DB credentials after a deploy.

Related errors


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