{"record":{"id":"95a89dbd68c97ffd","repo":"hashicorp/nomad","slug":"csi-nodedetachvolume-v","errorCode":null,"errorMessage":"CSI.NodeDetachVolume: %v","messagePattern":"CSI\\.NodeDetachVolume: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/csi_endpoint.go","lineNumber":521,"sourceCode":"\t// The following block of validation checks should not be reached on a\n\t// real Nomad cluster. They serve as a defensive check before forwarding\n\t// requests to plugins, and to aid with development.\n\tif req.PluginID == \"\" {\n\t\treturn errors.New(\"CSI.NodeDetachVolume: PluginID is required\")\n\t}\n\tif req.VolumeID == \"\" {\n\t\treturn errors.New(\"CSI.NodeDetachVolume: VolumeID is required\")\n\t}\n\tif req.AllocID == \"\" {\n\t\treturn errors.New(\"CSI.NodeDetachVolume: AllocID is required\")\n\t}\n\n\tctx, cancelFn := c.requestContext()\n\tdefer cancelFn()\n\n\tmanager, err := c.c.csimanager.ManagerForPlugin(ctx, req.PluginID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"CSI.NodeDetachVolume: %v\", err)\n\t}\n\n\tusageOpts := &csimanager.UsageOptions{\n\t\tReadOnly:       req.ReadOnly,\n\t\tAttachmentMode: req.AttachmentMode,\n\t\tAccessMode:     req.AccessMode,\n\t}\n\n\terr = manager.UnmountVolume(ctx, req.VolumeNamespace, req.VolumeID, req.ExternalID, req.AllocID, usageOpts)\n\tif err != nil && !errors.Is(err, nstructs.ErrCSIClientRPCIgnorable) {\n\t\t// if the unmounting previously happened but the server failed to\n\t\t// checkpoint, we'll get an error from Unmount but can safely\n\t\t// ignore it.\n\t\treturn fmt.Errorf(\"CSI.NodeDetachVolume: %v\", err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/csi_endpoint.go#L503-L539","documentation":"NodeDetachVolume is the client RPC endpoint that asks a CSI node plugin to unmount/detach a volume from an allocation. This error wraps a failure from csimanager.ManagerForPlugin, meaning the client could not locate or initialize a manager for the requested CSI plugin (req.PluginID). It aborts the detach before any unmount is attempted.","triggerScenarios":"An API caller (nomad volume detach / allocation stop) sends NodeDetachVolume with a PluginID for which no plugin instance exists on the client, the plugin is not running, or the plugin manager cannot be created for that plugin type.","commonSituations":"Volume deregistered or plugin upgraded/restarted on the node so the PluginID no longer matches a live plugin; typo'd or stale plugin ID after node restart; CSI plugin crashed so the manager for that plugin is unavailable.","solutions":["Verify the plugin ID in the detach request matches a running CSI plugin on the target node (nomad plugin status).","Restart or redeploy the CSI plugin task on the node so a manager can be created.","Check nomad agent logs on the client for the underlying ManagerForPlugin error to see whether the plugin failed to load or was deregistered.","Re-run the detach once the plugin is healthy; if the allocation is gone, the claim cleanup can be done from the server side."],"exampleFix":"// before: detaching with stale plugin id\nclient.CSIVolumes().Detach(ctx, &cstructs.ClientCSIDetachRequest{PluginID: \"old-plugin\", ...})\n// after: look up the live plugin first\npluginID := \"registry.aws.ebs\" // from `nomad plugin status`\nclient.CSIVolumes().Detach(ctx, &cstructs.ClientCSIDetachRequest{PluginID: pluginID, ...})","handlingStrategy":"try-catch","validationCode":"// confirm plugin exists before detaching\n// nomad plugin status <plugin-id>  -> must show node plugins\nif pluginStatus == nil || len(pluginStatus.NodePlugins) == 0 {\n  return fmt.Errorf(\"plugin %q not running on node\", pluginID)\n}","typeGuard":"func hasCSIPlugin(plugins []*api.Plugin, id string) bool {\n  for _, p := range plugins { if p.ID == id { return true } }\n  return false\n}","tryCatchPattern":"err := volumes.Detach(ctx, volID, nodeID, pluginID)\nif err != nil && strings.Contains(err.Error(), \"CSI.NodeDetachVolume\") {\n  // plugin unavailable: re-check plugin status and retry after plugin restart\n  log.Warnf(\"csi plugin %s unavailable: %v\", pluginID, err)\n}","preventionTips":["Confirm plugin ID with `nomad plugin status` before issuing detach calls","Ensure CSI plugin tasks restart automatically and re-register on client startup","Avoid deregistering volumes/plugins while allocations still reference them"],"tags":["csi","storage","plugin"],"backgroundTag":"csi-plugin-not-found","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"}