{"record":{"id":"81a56e90d2448484","repo":"semaphoreui/semaphore","slug":"task-is-not-active","errorCode":null,"errorMessage":"task is not active","messagePattern":"task is not active","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"services/tasks/TaskPool.go","lineNumber":637,"sourceCode":"\n\tres := proj.MaxParallelTasks > 0 && p.state.ActiveCount(t.Task.ProjectID) >= proj.MaxParallelTasks\n\n\tif res {\n\t\treturn true\n\t}\n\n\treturn res\n}\n\nfunc (p *TaskPool) ConfirmTask(targetTask db.Task) error {\n\ttsk, err := p.GetTask(targetTask.ID)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif tsk == nil { // task not active, but exists in database\n\t\treturn fmt.Errorf(\"task is not active\")\n\t}\n\n\ttsk.SetStatus(task_logger.TaskConfirmed)\n\n\treturn nil\n}\n\nfunc (p *TaskPool) RejectTask(targetTask db.Task) error {\n\ttsk, err := p.GetTask(targetTask.ID)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif tsk == nil { // task not active, but exists in database\n\t\treturn fmt.Errorf(\"task is not active\")\n\t}\n","sourceCodeStart":619,"sourceCodeEnd":655,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/services/tasks/TaskPool.go#L619-L655","documentation":"ConfirmTask transitions a pending task to the confirmed state by looking it up in the in-memory task pool. When the task is not in the pool (nil) the comment notes it 'exists in database' but is not active locally — typically already finished, restarted, or evicted — so confirmation is refused with this error.","triggerScenarios":"Calling ConfirmTask with a task ID whose in-memory representation has been removed: the task already ran/finished, the server restarted losing the pool, or the ID never belonged to an active task on this instance.","commonSituations":"Confirming a task twice (second call finds nothing active); delayed confirmation after the task timed out or completed; multi-instance setups where the task was scheduled on another node; server restart mid-workflow.","solutions":["Check the task's current state before confirming; skip confirmation if it already finished","Treat this as a benign race in idempotent clients — log and continue instead of failing hard","Re-run/re-trigger the task if a fresh confirmation cycle is genuinely needed","Verify only one server instance manages the task pool (or use a shared/stateful setup)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// confirm only while task is pending\nif tsk.Status != taskStatusPending { /* skip confirmation */ }","typeGuard":null,"tryCatchPattern":"if err := pool.ConfirmTask(taskID, ...); err != nil {\n    if strings.Contains(err.Error(), \"task is not active\") {\n        return nil // already finished/rejected; idempotent no-op\n    }\n    return err\n}","preventionTips":["Make confirmation idempotent — ignore 'not active' for resolved tasks","Avoid confirming the same task twice concurrently","Route task management to the instance owning the task pool","Re-fetch task state after server restarts"],"tags":["go","tasks","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa","analyzedAt":"2026-09-07T11:00:33.293Z","contentChangedAt":"2026-09-07T11:00:33.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}