semaphoreui/semaphore · error

task not found

Error message

task not found

What it means

RemoteJob.Run looks up the task by ID before executing it remotely; if the database lookup succeeds but returns no task, Run fails with 'task not found'. This protects against running jobs for tasks that were deleted or belong to another project while the job was queued.

Solutions

  1. Check the task still exists (GET /project/{project_id}/tasks/{task_id}) before/while the job runs
  2. Do not delete tasks while their jobs are queued; cancel the job first
  3. Verify all server replicas connect to the same primary database
  4. Confirm the task ID used by the job scheduler matches a real task
Defensive patterns

Strategy: try-catch

Validate before calling

tsk, err := dbStore.GetTask(projectID, taskID)
if err != nil || tsk == nil { /* do not schedule the job */ }

Try / catch

if err := job.Run(...); err != nil {
    if strings.Contains(err.Error(), "task not found") {
        log.Printf("task %d vanished before run; skipping", taskID)
        return nil // treat as benign
    }
    return err
}

Prevention

When it happens

Trigger: Calling Run for a task ID that no longer exists in the database — the task was deleted between scheduling and execution, the ID is wrong, or the DB connection points to a different/rolled-back database.

Common situations: Task canceled/deleted while a remote job was still pending; stale job records replayed after a database restore; server replicas pointing at different databases; passing an incorrect task ID to the internal job runner.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07). Data as JSON: /api/errors/c6e17c5c9d076a6b. Report an issue: GitHub.

Appendix: source

Thrown at services/tasks/RemoteJob.go:142

		if !r.IsOnline(now, offlineTimeout) {
			continue
		}
		if n := busyTasks(r.ID); n < r.MaxParallelTasks || r.MaxParallelTasks == 0 {
			return r
		}
	}
	return nil
}

func (t *RemoteJob) Run(username string, incomingVersion *string, alias string) (err error) {
	tsk, err := t.taskPool.GetTask(t.Task.ID)

	if err != nil {
		return
	}

	if tsk == nil {
		return fmt.Errorf("task not found")
	}

	tsk.IncomingVersion = incomingVersion
	tsk.Username = username
	tsk.Alias = alias
	t.taskPool.state.UpdateRuntimeFields(tsk)

	var runners []db.Runner
	tagFilterMode := db.RunnerFilterTagCompleteMatch
	if t.RunnerTag == nil {
		tagFilterMode = db.RunnerFilterIsDefault
	}

	var projectRunners []db.Runner
	projectRunners, err = t.taskPool.store.GetRunners(t.Task.ProjectID, true, tagFilterMode, t.RunnerTag)
	if err != nil {
		return
	}

View on GitHub (pinned to 1774ccb71a)