{"record":{"id":"2d3f382b88ef3f4e","repo":"hashicorp/nomad","slug":"namespace-q-contains-at-least-one-csi-volume-q","errorCode":null,"errorMessage":"namespace %q contains at least one CSI volume %q. All CSI volumes in namespace must be deleted before it can be deleted","messagePattern":"namespace %q contains at least one CSI volume %q\\. All CSI volumes in namespace must be deleted before it can be deleted","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/state/state_store.go","lineNumber":7157,"sourceCode":"\t\t\tif raw == nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tjob := raw.(*structs.Job)\n\n\t\t\tif job.Status != structs.JobStatusDead {\n\t\t\t\treturn fmt.Errorf(\"namespace %q contains at least one non-terminal job %q. \"+\n\t\t\t\t\t\"All jobs must be terminal in namespace before it can be deleted\", name, job.ID)\n\t\t\t}\n\t\t}\n\n\t\tvIter, err := s.csiVolumesByNamespaceImpl(txn, nil, name, \"\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\trawVol := vIter.Next()\n\t\tif rawVol != nil {\n\t\t\tvol := rawVol.(*structs.CSIVolume)\n\t\t\treturn fmt.Errorf(\"namespace %q contains at least one CSI volume %q. \"+\n\t\t\t\t\"All CSI volumes in namespace must be deleted before it can be deleted\", name, vol.ID)\n\t\t}\n\n\t\tvarIter, err := s.getVariablesByNamespaceImpl(txn, nil, name)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif varIter.Next() != nil {\n\t\t\t// unlike job/volume, don't show the path here because the user may\n\t\t\t// not have List permissions on the vars in this namespace\n\t\t\treturn fmt.Errorf(\"namespace %q contains at least one variable. \"+\n\t\t\t\t\"All variables in namespace must be deleted before it can be deleted\", name)\n\t\t}\n\n\t\t// Delete the namespace\n\t\tif err := txn.Delete(TableNamespaces, existing); err != nil {\n\t\t\treturn fmt.Errorf(\"namespace deletion failed: %v\", err)\n\t\t}","sourceCodeStart":7139,"sourceCodeEnd":7175,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/state/state_store.go#L7139-L7175","documentation":"DeleteNamespace checks for CSI volumes registered in the namespace and refuses deletion if any exist. CSI volume objects must be explicitly deregistered/deleted first; the error names the volume ID that blocks deletion.","triggerScenarios":"DELETE /v1/namespace/<name> while a CSI volume (from a `volume` block or CSI plugin registration) is still registered in that namespace.","commonSituations":"Decommissioning a namespace that used host/CSI storage; volumes left behind after jobs were stopped because CSI volumes are not garbage-collected with jobs.","solutions":["Deregister the volume: `nomad volume deregister -namespace <ns> <volume-id>` (or `nomad volume delete` for per-alloc CSI volumes), then retry namespace deletion.","Ensure the storage plugin/node providing the volume is drained so claims can be released.","Delete any jobs claiming the volume first, since claimed volumes may not be deletable."],"exampleFix":"# before\nnomad namespace delete storage-team\n# after\nnomad volume deregister -namespace storage-team <volume-id>\nnomad namespace delete storage-team","handlingStrategy":"validation","validationCode":"vols, _, _ := client.CSIVolumes().List(&nomad.QueryOptions{Namespace: ns})\nif len(vols) > 0 {\n    return fmt.Errorf(\"%d CSI volumes still registered in %s\", len(vols), ns)\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"CSI volume\") {\n    // deregister the volume named in the message, then retry\n}","preventionTips":["Deregister CSI volumes as part of namespace decommissioning, after stopping claiming jobs.","Track volume ownership per namespace in your provisioning tooling."],"tags":["nomad","state-store","namespace","csi"],"backgroundTag":"namespace-not-empty","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"}