{"record":{"id":"d31c37c08ba75997","repo":"hashicorp/nomad","slug":"handle-cannot-be-nil-d31c37","errorCode":null,"errorMessage":"handle cannot be nil","messagePattern":"handle cannot be nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"drivers/rawexec/driver.go","lineNumber":316,"sourceCode":"\tif d.config.Enabled {\n\t\thealth = drivers.HealthStateHealthy\n\t\tdesc = drivers.DriverHealthy\n\t\tattrs[\"driver.raw_exec\"] = pstructs.NewBoolAttribute(true)\n\t} else {\n\t\thealth = drivers.HealthStateUndetected\n\t\tdesc = \"disabled\"\n\t}\n\n\treturn &drivers.Fingerprint{\n\t\tAttributes:        attrs,\n\t\tHealth:            health,\n\t\tHealthDescription: desc,\n\t}\n}\n\nfunc (d *Driver) RecoverTask(handle *drivers.TaskHandle) error {\n\tif handle == nil {\n\t\treturn fmt.Errorf(\"handle cannot be nil\")\n\t}\n\n\t// If already attached to handle there's nothing to recover.\n\tif _, ok := d.tasks.Get(handle.Config.ID); ok {\n\t\td.logger.Trace(\"nothing to recover; task already exists\",\n\t\t\t\"task_id\", handle.Config.ID,\n\t\t\t\"task_name\", handle.Config.Name,\n\t\t)\n\t\treturn nil\n\t}\n\n\t// Handle doesn't already exist, try to reattach\n\tvar taskState TaskState\n\tif err := handle.GetDriverState(&taskState); err != nil {\n\t\td.logger.Error(\"failed to decode task state from handle\", \"error\", err, \"task_id\", handle.Config.ID)\n\t\treturn fmt.Errorf(\"failed to decode task state from handle: %v\", err)\n\t}\n","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/rawexec/driver.go#L298-L334","documentation":"RecoverTask guards against a nil TaskHandle argument and returns this error immediately. RecoverTask is used on client restart to reattach to a running task's handle; a nil handle means the caller passed invalid state.","triggerScenarios":"Calling Driver.RecoverTask(nil) — typically a programming bug in the client's task restore path rather than a runtime condition.","commonSituations":"Plugin/client restore logic after an agent crash passing an unmarshalled empty handle; custom tooling invoking the driver plugin API directly with missing handle data.","solutions":["Pass a valid *drivers.TaskHandle restored from the client's task state","Check the client restore code path: a nil handle usually means the task state on disk is missing/corrupt","As a caller, check the error and skip/invalidate the task rather than retrying with nil"],"exampleFix":"// before\nerr := driver.RecoverTask(nil) // handle cannot be nil\n// after\nhandle, ok := restoredHandles[taskID]\nif !ok {\n    return fmt.Errorf(\"no restored handle for task %s\", taskID)\n}\nerr := driver.RecoverTask(handle)","handlingStrategy":"type-guard","validationCode":"if handle == nil {\n    return errors.New(\"refusing to recover: nil task handle\")\n}","typeGuard":"func validHandle(h *drivers.TaskHandle) bool { return h != nil && h.Config != nil && h.Config.ID != \"\" }","tryCatchPattern":"if err := drv.RecoverTask(handle); err != nil && err.Error() == \"handle cannot be nil\" {\n    // treat as restore bug; re-create or invalidate the task\n}","preventionTips":["Never pass an unverified handle to RecoverTask","Validate restored task state before recovery after client restarts","Handle nil gracefully in restore code paths"],"tags":["raw-exec","recover","nil-argument","nomad-driver"],"backgroundTag":"nil-handle-argument","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"}