{"record":{"id":"a38fd89e0a9e1cec","repo":"hashicorp/nomad","slug":"task-with-id-q-already-started-a38fd8","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/rawexec/driver.go","lineNumber":397,"sourceCode":"\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif !found {\n\t\t\tenvList = append(envList, k+\"=\"+v)\n\t\t}\n\t}\n\tsort.Strings(envList)\n\treturn envList\n}\n\nfunc (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drivers.DriverNetwork, error) {\n\tif !d.config.Enabled {\n\t\treturn nil, nil, errDisabledDriver\n\t}\n\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\tdriverConfig.OverrideCgroupV2 = cgroupslib.CustomPathCG2(driverConfig.OverrideCgroupV2)\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 err := d.Validate(*cfg); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed driver config validation: %v\", err)\n\t}\n\n\td.logger.Info(\"starting task\", \"driver_cfg\", hclog.Fmt(\"%+v\", driverConfig))","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/rawexec/driver.go#L379-L415","documentation":"StartTask rejects a task whose ID is already tracked by this driver instance, meaning a taskHandle already exists in d.tasks for cfg.ID. This is an internal invariant guard: the same task ID must not be started twice. It usually surfaces after a client-side retry that didn't notice the earlier start succeeded.","triggerScenarios":"Calling StartTask with a TaskConfig whose ID is already present in the driver's task map — e.g. Nomad client retrying StartTask after an RPC timeout, or RecoverTask/StartTask racing on the same task.","commonSituations":"RPC retries from client to driver plugin after network hiccups; duplicate task IDs from a corrupted client state; running a single nomad client process with duplicated alloc assignments.","solutions":["Let the client reconcile: the existing handle is still valid, so the client should call it via RecoverTask/its existing handle instead of starting again","Restart the nomad client agent if its task map is stale/duplicated","Report to Nomad if reproducible — this indicates a client-side race and should not happen under normal operation","Check for multiple nomad client processes accidentally running against the same data_dir"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// caller: check driver doesn't already track the task before StartTask\n// (client side) ensure only one StartTask per task ID is in flight\nif started[taskID] { return existingHandle, nil }","typeGuard":"func isAlreadyStarted(err error) bool {\n  var pe *strings.Reader // message-based guard\n  return err != nil && strings.Contains(err.Error(), \"already started\")\n}","tryCatchPattern":"h, net, err := d.StartTask(cfg)\nif err != nil && strings.Contains(err.Error(), \"already started\") {\n  // treat as success-ish: retrieve existing handle via RecoverTask\n  return d.RecoverTask(cfg.ID)\n}","preventionTips":["Serialize StartTask calls per task ID","Avoid aggressive RPC retries without idempotency handling","Run exactly one nomad client per data_dir","Report races to Nomad — user code should rarely see this"],"tags":["nomad","rawexec","duplicate-task","starttask"],"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-08T10:18:20.063Z"}