{"record":{"id":"15f1b58841a0bfd1","repo":"hashicorp/nomad","slug":"task-with-id-q-already-started-15f1b5","errorCode":null,"errorMessage":"task with ID %q already started","messagePattern":"task with ID %q already started","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/exec/driver.go","lineNumber":460,"sourceCode":"\t\texec:         exec,\n\t\tpid:          taskState.Pid,\n\t\tpluginClient: pluginClient,\n\t\ttaskConfig:   taskState.TaskConfig,\n\t\tprocState:    drivers.TaskStateRunning,\n\t\tstartedAt:    taskState.StartedAt,\n\t\texitResult:   &drivers.ExitResult{},\n\t\tlogger:       d.logger,\n\t}\n\n\td.tasks.Set(taskState.TaskConfig.ID, h)\n\n\tgo h.run()\n\treturn nil\n}\n\nfunc (d *Driver) StartTask(cfg *drivers.TaskConfig) (handle *drivers.TaskHandle, network *drivers.DriverNetwork, err error) {\n\tif _, ok := d.tasks.Get(cfg.ID); ok {\n\t\treturn nil, nil, fmt.Errorf(\"task with ID %q already started\", cfg.ID)\n\t}\n\n\tvar driverConfig TaskConfig\n\tif err := cfg.DecodeDriverConfig(&driverConfig); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to decode driver config: %v\", err)\n\t}\n\n\tif err := driverConfig.validate(); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed driver config validation: %v\", err)\n\t}\n\n\tif cfg.User == \"\" {\n\t\tcfg.User = \"nobody\"\n\t}\n\n\td.logger.Debug(\"setting up user\", \"user\", cfg.User)\n\n\tif err := d.userIDValidator.HasValidIDs(cfg.User); err != nil {","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/exec/driver.go#L442-L478","documentation":"StartTask checks the driver's in-memory task map for cfg.ID before doing any work. If a task with the same ID is already tracked by this driver instance, it refuses to start a duplicate and returns this error. It is a guard against double-starting the same allocation's task.","triggerScenarios":"Calling StartTask twice with the same drivers.TaskConfig.ID without an intervening StopTask/destroy; a task handle left in d.tasks because a prior StartTask partially failed after registering.","commonSituations":"Bug in custom tooling that invokes the driver plugin API directly; a retried StartTask RPC after a timeout where the first call actually succeeded; leaked handle after a failed shutdown.","solutions":["Check task status before starting; call StopTask/DestroyTask on the existing handle if the task should be restarted.","Verify your client code is not retrying StartTask on timeout without checking state first.","Restart the Nomad client to clear leaked in-memory handles if the underlying task is provably dead."],"exampleFix":"// before\nhandle, _, _ := drv.StartTask(cfg) // retried blindly\n// after\nif _, ok := drv.InspectTask(cfg.ID); ok {\n    _ = drv.StopTask(cfg.ID, 0, \"restarting\")\n    _ = drv.DestroyTask(cfg.ID, false)\n}\nhandle, _, err := drv.StartTask(cfg)","handlingStrategy":"validation","validationCode":"// guard caller side before starting\nif _, err := drv.InspectTask(cfg.ID); err == nil {\n    return fmt.Errorf(\"task %s already running; stop it first\", cfg.ID)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Track StartTask calls in a map/set keyed by task ID in your orchestration code.","On StartTask timeout, check task state before retrying instead of blindly re-calling.","Always pair StartTask with StopTask/DestroyTask in cleanup paths."],"tags":["nomad","exec-driver","duplicate-task","state-conflict"],"backgroundTag":"task-already-started","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}