hashicorp/nomad · error

task with ID %q already started

Error message

task with ID %q already started

What it means

This error is returned by StartTask when a task with the same ID is already tracked by the driver in its in-memory tasks map. Nomad task IDs are unique per allocation, so this indicates duplicate startup for the same task, most often a race or a client bug that calls StartTask twice. It prevents double-running the same task within the driver.

Source

Thrown at drivers/java/driver.go:434

		exec:         execImpl,
		pid:          taskState.Pid,
		pluginClient: pluginClient,
		taskConfig:   taskState.TaskConfig,
		procState:    drivers.TaskStateRunning,
		startedAt:    taskState.StartedAt,
		exitResult:   &drivers.ExitResult{},
		logger:       d.logger,
	}

	d.tasks.Set(taskState.TaskConfig.ID, h)

	go h.run()
	return nil
}

func (d *Driver) StartTask(cfg *drivers.TaskConfig) (handle *drivers.TaskHandle, network *drivers.DriverNetwork, err error) {
	if _, ok := d.tasks.Get(cfg.ID); ok {
		return nil, nil, fmt.Errorf("task with ID %q already started", cfg.ID)
	}

	var driverConfig TaskConfig
	if err := cfg.DecodeDriverConfig(&driverConfig); err != nil {
		return nil, nil, fmt.Errorf("failed to decode driver config: %v", err)
	}

	if err := driverConfig.validate(); err != nil {
		return nil, nil, fmt.Errorf("failed driver config validation: %v", err)
	}

	if driverConfig.Class == "" && driverConfig.JarPath == "" {
		return nil, nil, fmt.Errorf("jar_path or class must be specified")
	}

	absPath, err := GetAbsolutePath("java")
	if err != nil {
		return nil, nil, fmt.Errorf("failed to find java binary: %s", err)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the task ID is unique per allocation and not reused
  2. Check whether the task is already running (d.tasks / nomad alloc status) before starting
  3. Stop the existing task/allocation before starting a new one with the same ID
  4. If caused by a race or recovery bug, restart the Nomad client and report the issue

Example fix

// before
handle, _, _ := driver.StartTask(cfg) // called twice for same cfg.ID
// after
if _, ok := driver.(*javaDriver).tasks.Get(cfg.ID); !ok {
    handle, _, _ = driver.StartTask(cfg)
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure unique task IDs before starting
ids := map[string]bool{}
for _, t := range group.Tasks {
    if ids[t.Name] { return errors.New("duplicate task id") }
    ids[t.Name] = true
}

Try / catch

if _, _, err := driver.StartTask(cfg); err != nil {
    if strings.Contains(err.Error(), "already started") {
        // treat as success or stop the existing task first
    }
}

Prevention

When it happens

Trigger: Calling StartTask twice with a *drivers.TaskConfig whose ID is already present in d.tasks; concurrent starts racing past the Get check; client state restore followed by an explicit start.

Common situations: Driver plugin bugs or custom automation invoking the driver directly; recovery logic replaying starts; test harnesses reusing task IDs without cleanup.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/36d76e5477ee372e. Report an issue: GitHub.