{"record":{"id":"677df0224722eba1","repo":"Billionmail/BillionMail","slug":"task-d-not-found","errorCode":null,"errorMessage":"task %d not found","messagePattern":"task (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/batch_mail/task_executor.go","lineNumber":1475,"sourceCode":"\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\n\tvar runningWorkers int\n\tif e.pool != nil {\n\t\toldPoolSize = e.pool.Cap()\n\t\trunningWorkers = e.pool.Running()\n\t}\n\n\t// new threads\n\tnewThreads := threads\n\t// calculate new rate limit - 20 emails per thread per second\n\ttargetSendPerThreadPerSecond := 20\n\tnewRate := newThreads * targetSendPerThreadPerSecond * 60\n\n\t// create new rate controller\n\te.rateController = NewSimpleRateController(newRate)","sourceCodeStart":1457,"sourceCodeEnd":1493,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/batch_mail/task_executor.go#L1457-L1493","documentation":"UpdateTaskThreads checks the task returned by GetTaskInfo and rejects the update with \"task %d not found\" when the record is nil or has Id == 0. This distinguishes a successful lookup with no matching row from a hard database failure.","triggerScenarios":"Calling UpdateTaskThreads with a taskId that does not exist in the tasks table, references a deleted task, or where GetTaskInfo returns an empty struct for an id-only filter miss.","commonSituations":"Stale UI list showing a task deleted by another admin; off-by-one or wrong-type ids (string id parsed to 0) from client requests; tasks removed by a cleanup job while an update was in flight.","solutions":["Verify the taskId exists (query the tasks table or refresh the task list).","In the caller, validate taskId > 0 and handle 'not found' by reloading current tasks before updating.","If the task was deleted, recreate it or drop the pending update rather than retrying.","Check for soft-delete/tenant filters in GetTaskInfo that may hide the row legitimately."],"exampleFix":"// before: no existence check client-side\nawait api.updateTaskThreads(deletedTaskId, 10)\n// after\nconst task = tasks.value.find(t => t.id === taskId)\nif (!task) { message.error('Task no longer exists'); return }\nawait api.updateTaskThreads(task.id, 10)","handlingStrategy":"validation","validationCode":"// Go: confirm the task exists before updating\ntask, err := GetTaskInfo(context.Background(), taskId)\nif err != nil { return err }\nif task == nil || task.Id == 0 {\n    return fmt.Errorf(\"task %d not found; refresh task list\", taskId)\n}","typeGuard":"func taskExists(taskId int, tasks []*model.Task) bool {\n    return taskId > 0 && slices.ContainsFunc(tasks, func(t *model.Task) bool { return t.Id == taskId })\n}","tryCatchPattern":"if err := executor.UpdateTaskThreads(taskId, threads); err != nil {\n    if strings.Contains(err.Error(), fmt.Sprintf(\"task %d not found\", taskId)) {\n        // reload tasks in UI / remove stale entry; do not retry blindly\n        return ErrTaskGone\n    }\n    return err\n}","preventionTips":["Refresh task lists after deletions and before issuing updates.","Validate taskId > 0 at the handler (a missing param decodes to 0).","Treat 'not found' as terminal: never auto-retry with the same id.","Check soft-delete filters if a task should exist but is reported missing."],"tags":["not-found","validation","batch-mail"],"backgroundTag":"resource-not-found","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"}