{"record":{"id":"e2afff7fe63488e8","repo":"hashicorp/nomad","slug":"plugin-in-use","errorCode":null,"errorMessage":"plugin in use","messagePattern":"plugin in use","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"nomad/structs/errors.go","lineNumber":93,"sourceCode":"\n\tErrUnknownNode = errors.New(ErrUnknownNodePrefix)\n\n\tErrDeploymentTerminalNoCancel    = errors.New(errDeploymentTerminalNoCancel)\n\tErrDeploymentTerminalNoFail      = errors.New(errDeploymentTerminalNoFail)\n\tErrDeploymentTerminalNoPause     = errors.New(errDeploymentTerminalNoPause)\n\tErrDeploymentTerminalNoPromote   = errors.New(errDeploymentTerminalNoPromote)\n\tErrDeploymentTerminalNoResume    = errors.New(errDeploymentTerminalNoResume)\n\tErrDeploymentTerminalNoUnblock   = errors.New(errDeploymentTerminalNoUnblock)\n\tErrDeploymentTerminalNoRun       = errors.New(errDeploymentTerminalNoRun)\n\tErrDeploymentTerminalNoSetHealth = errors.New(errDeploymentTerminalNoSetHealth)\n\tErrDeploymentRunningNoUnblock    = errors.New(errDeploymentRunningNoUnblock)\n\n\tErrCSIClientRPCIgnorable  = errors.New(\"CSI client error (ignorable)\")\n\tErrCSIClientRPCRetryable  = errors.New(\"CSI client error (retryable)\")\n\tErrCSIVolumeMaxClaims     = errors.New(\"volume max claims reached\")\n\tErrCSIVolumeUnschedulable = errors.New(\"volume is currently unschedulable\")\n\tErrCSIPluginInUse         = errors.New(\"plugin in use\")\n)\n\n// IsErrNoLeader returns whether the error is due to there being no leader.\nfunc IsErrNoLeader(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), errNoLeader)\n}\n\n// IsErrNoRegionPath returns whether the error is due to there being no path to\n// the given region.\nfunc IsErrNoRegionPath(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), errNoRegionPath)\n}\n\n// IsErrTokenNotFound returns whether the error is due to the passed token not\n// being resolvable.\nfunc IsErrTokenNotFound(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), errTokenNotFound)\n}\n","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/errors.go#L75-L111","documentation":"ErrCSIPluginInUse is returned when deleting a CSI plugin that still has volumes registered against it. The state store treats this as an error for the Delete operation, but callers like the FSM and CSI endpoint deliberately suppress logging for it because 'plugin in use' is an expected, non-exceptional condition for typical callers.","triggerScenarios":"Calling CSIVolume plugin delete ('nomad plugin delete' / CSIPlugin.Delete RPC, raft CSIPluginDeleteRequestType) while volumes from that plugin still exist in state; also raised by the state store during DeleteCSIPlugin in the FSM.","commonSituations":"Operator garbage-collects plugins after decommissioning a node but forgot to purge its volumes; deregistering a plugin during cleanup scripts while claims remain; job using the volume is still running.","solutions":["Delete/deregister all CSI volumes belonging to the plugin first ('nomad volume deregister <id>'), then delete the plugin","Stop any jobs still using the plugin's volumes so claims are released","Use 'nomad node eligibility' / drain and wait for allocations to move before plugin cleanup","Treat the error as an expected outcome in automation: skip or defer deletion when errors.Is(err, structs.ErrCSIPluginInUse)"],"exampleFix":"// before\n_, _, err := client.NodePlugins().Delete(pluginID, nil)\nif err != nil { return err }\n// after\n_, _, err := client.NodePlugins().Delete(pluginID, nil)\nif err != nil && errors.Is(err, structs.ErrCSIPluginInUse) {\n    return nil // plugin still has volumes; delete later\n}\nif err != nil { return err }","handlingStrategy":"try-catch","validationCode":"plugin, _, err := client.CSIPlugins().Info(pluginID, nil)\nif err == nil && plugin != nil && plugin.Volumes != nil {\n    for _, vols := range plugin.Volumes {\n        if len(vols) > 0 {\n            return fmt.Errorf(\"plugin %s still has %d volumes\", pluginID, len(vols))\n        }\n    }\n}","typeGuard":"func pluginInUseErr(err error) bool {\n    return errors.Is(err, structs.ErrCSIPluginInUse)\n}","tryCatchPattern":"_, _, err := client.NodePlugins().Delete(pluginID, nil)\nif err != nil && errors.Is(err, structs.ErrCSIPluginInUse) {\n    log.Printf(\"plugin %s still in use; deferring delete\", pluginID)\n    return nil\n}\nreturn err","preventionTips":["Deregister all volumes of a plugin before deleting it","Stop dependent jobs and wait for claims to clear before cleanup","In automation, treat ErrCSIPluginInUse as expected and defer deletion"],"tags":["csi","storage","nomad","cleanup"],"backgroundTag":"plugin-in-use","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"}