hashicorp/nomad · error
volume max claims reached
Error message
volume max claims reached
What it means
ErrCSIVolumeMaxClaims is returned when a volume claim would exceed the allowed number of concurrent claims — Nomad permits only one writer (or the configured ReadSched/WriteSched reader count) per volume. The state store rejects the Claim RPC when the volume's capacity for concurrent access is exhausted.
Source
Thrown at nomad/structs/errors.go:91
// Keep the two in sync.
ErrResultPaginatorCreation = errors.New(errResultPaginatorCreation)
ErrUnknownNode = errors.New(ErrUnknownNodePrefix)
ErrDeploymentTerminalNoCancel = errors.New(errDeploymentTerminalNoCancel)
ErrDeploymentTerminalNoFail = errors.New(errDeploymentTerminalNoFail)
ErrDeploymentTerminalNoPause = errors.New(errDeploymentTerminalNoPause)
ErrDeploymentTerminalNoPromote = errors.New(errDeploymentTerminalNoPromote)
ErrDeploymentTerminalNoResume = errors.New(errDeploymentTerminalNoResume)
ErrDeploymentTerminalNoUnblock = errors.New(errDeploymentTerminalNoUnblock)
ErrDeploymentTerminalNoRun = errors.New(errDeploymentTerminalNoRun)
ErrDeploymentTerminalNoSetHealth = errors.New(errDeploymentTerminalNoSetHealth)
ErrDeploymentRunningNoUnblock = errors.New(errDeploymentRunningNoUnblock)
ErrCSIClientRPCIgnorable = errors.New("CSI client error (ignorable)")
ErrCSIClientRPCRetryable = errors.New("CSI client error (retryable)")
ErrCSIVolumeMaxClaims = errors.New("volume max claims reached")
ErrCSIVolumeUnschedulable = errors.New("volume is currently unschedulable")
ErrCSIPluginInUse = errors.New("plugin in use")
)
// IsErrNoLeader returns whether the error is due to there being no leader.
func IsErrNoLeader(err error) bool {
return err != nil && strings.Contains(err.Error(), errNoLeader)
}
// IsErrNoRegionPath returns whether the error is due to there being no path to
// the given region.
func IsErrNoRegionPath(err error) bool {
return err != nil && strings.Contains(err.Error(), errNoRegionPath)
}
// IsErrTokenNotFound returns whether the error is due to the passed token not
// being resolvable.
func IsErrTokenNotFound(err error) bool {
return err != nil && strings.Contains(err.Error(), errTokenNotFound)View on GitHub (pinned to 482b49bf1a)
Solutions
- Release the existing claim (stop the other allocation, or use CSIVolume.Unclaim / 'nomad volume detach <vol> <alloc>') and retry
- Configure the volume as multi-writer (csi_plugin/mount_flags with MULTI_NODE_MULTI_WRITER capability) if concurrent writes are truly intended — only if the storage backend supports it
- Use volume scaling/clone or a second volume so each writer has its own volume
- Verify no orphaned claims from crashed allocations exist (access mode/attachment status in 'nomad volume status') and clean them up
Example fix
// before
job uses volume "data" with access_mode = "single-node-writer" on 2 allocations
// after
# either run a single writer allocation, or declare the volume with
# capability MULTI_NODE_MULTI_WRITER and access_mode = "multi-node-multi-writer"
volume "data" {
type = "csi"
source = "data"
access_mode = "multi-node-multi-writer"
attachment_mode = "file-system"
} Defensive patterns
Strategy: validation
Validate before calling
vol, _, _ := client.CSIVolumes().Info(volID, nil)
if vol != nil {
for _, a := range vol.Allocations {
if a.Mode == "single-node-writer" {
return fmt.Errorf("volume %s write claim held by alloc %s", volID, a.ID)
}
}
} Type guard
func volumeWritable(vol *api.CSIVolume) bool {
return vol != nil && vol.WriteAllocs != nil && len(vol.WriteAllocs) == 0
} Try / catch
err := claimVolume(volID, allocID)
if err != nil && strings.Contains(err.Error(), structs.ErrCSIVolumeMaxClaims.Error()) {
return fmt.Errorf("volume %s already claimed; unclaim or provision another", volID)
} Prevention
- Ensure only one allocation requests write access per single-writer volume
- Release claims (volume detach/deregister) when allocations are recycled
- Provision per-consumer volumes or use multi-writer capabilities where supported
- Check 'nomad volume status' for existing claims before scheduling writers
When it happens
Trigger: Calling CSIVolume.Claim with a write claim while another allocation already holds the write claim, or exceeding max reader claims; observed in isRetryableClaimRPCError and volume claim endpoints/tests.
Common situations: Two jobs (or two allocations of one job) both request exclusive access to the same host volume; an old allocation's claim was not released (stale claim) so the new one is rejected; scaling a service that shares a single-writer volume.
Related errors
- CSI.ControllerAttachVolume: VolumeID is required
- CSI.ControllerAttachVolume: ClientCSINodeID is required
- CSI.ControllerDetachVolume: VolumeID is required
- CSI.ControllerDetachVolume: ClientCSINodeID is required
- CSI.NodeDetachVolume: PluginID is required
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/17d8158a16a84b1a.
Report an issue: GitHub.