hashicorp/nomad · error
claiming volumes
Error message
claiming volumes: %w
What it means
After restoring mounts, the CSI hook's Prerun claims each requested volume via claimVolumes so the allocation holds a claim on the CSI volume. This error wraps failures in acquiring those claims, e.g. the volume doesn't exist, access mode conflicts, or the controller rejects the claim.
Solutions
- Run nomad volume status <volume> to confirm the volume exists and check its claims/capabilities
- Align the job's volume block (access_mode, attachment_mode, mount_flags) with the plugin's declared capabilities
- Free conflicting claims (stop other allocs or nomad volume detach) for single-writer volumes
- Ensure the CSI controller plugin is running and reachable, then reschedule the job
Example fix
// before
volume "data" { type = "csi" ... access_mode = "single-node-writer" } # already claimed elsewhere
// after
$ nomad volume detach data <other-node>
# or change job:
access_mode = "multi-node-multi-writer" # if plugin supports it Defensive patterns
Strategy: validation
Validate before calling
const vol = await nomad.get(`volume/csi/${volumeName}`);
const caps = vol.RequestedCapabilities ?? [];
if (!caps.some(c => c.AccessMode === 'single-node-writer'))
throw new Error(`volume ${volumeName} lacks required access mode`);
if (vol.Claims && vol.Claims.length >= 1 && mode === 'single-node-writer')
throw new Error('volume already claimed; free the claim first'); Try / catch
try {
await runJob(job);
} catch (err) {
if (String(err).includes('claiming volumes')) {
const claims = await nomad.get(`volume/csi/${volumeName}`);
for (const c of claims.Claims ?? []) await nomad.volumeDetach(volumeName, c.NodeID);
await runJob(job); // retry once after clearing claims
} else throw err;
} Prevention
- Match job volume access_mode/attachment_mode to the plugin's supported capabilities
- Detach stale claims before rescheduling single-writer volumes
- Verify volume registration (nomad volume register) before submitting jobs
- Keep CSI controller reachable so claim RPCs succeed
When it happens
Trigger: csiHook.Prerun() -> c.claimVolumes(c.volumeResults) returns an error: volume not found/registered, incompatible volume access mode/capabilities with the task's request, or RPC error to the CSI controller plugin.
Common situations: Job references a volume that was deregistered; host_volume/CSI volume requested with capabilities (access mode, fs type, mount flags) the plugin doesn't support; claim count exceeded for a single-node-reader/writer volume; CSI plugin down.
Related errors
- restoring mounts
- cannot change attachment mode of claimed volume
- cannot find node for plugin instance
- Claim.AllocationID is required
- Claim is required
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/3acfa1793ebcc305.
Report an issue: GitHub.
Appendix: source
Thrown at client/allocrunner/csi_hook.go:131
// Initially, populate the result map with all of the requests
for alias, volumeRequest := range tg.Volumes {
if volumeRequest.Type == structs.VolumeTypeCSI {
c.volumeResults[alias] = &volumePublishResult{
request: volumeRequest,
stub: &state.CSIVolumeStub{
VolumeID: volumeRequest.VolumeID(c.alloc.Name)},
}
}
}
err := c.restoreMounts(c.volumeResults)
if err != nil {
return fmt.Errorf("restoring mounts: %w", err)
}
err = c.claimVolumes(c.volumeResults)
if err != nil {
return fmt.Errorf("claiming volumes: %w", err)
}
err = c.mountVolumes(c.volumeResults)
if err != nil {
return fmt.Errorf("mounting volumes: %w", err)
}
// make the mounts available to the taskrunner's volume_hook
mounts := helper.ConvertMap(c.volumeResults,
func(result *volumePublishResult) *csimanager.MountInfo {
return result.stub.MountInfo
})
c.hookResources.SetCSIMounts(mounts)
// persist the published mount info so we can restore on client restarts
stubs := helper.ConvertMap(c.volumeResults,
func(result *volumePublishResult) *state.CSIVolumeStub {
return result.stubView on GitHub (pinned to 482b49bf1a)