hashicorp/nomad · error
cannot update volume %q: volume does not exist
Error message
cannot update volume %q: volume does not exist
What it means
When the submitted volume carries an explicit ID, validateVolumeUpdate treats the request as an update and looks up the existing volume. If no volume with that ID exists in the namespace, Nomad rejects the request with this message rather than silently creating a new volume. Updates and creates are distinguished solely by the presence of vol.ID.
Source
Thrown at nomad/host_volume_endpoint.go:438
}
ns, err := snap.NamespaceByName(nil, vol.Namespace)
if err != nil {
return nil, err // should never hit, bail out
}
if ns == nil {
return nil, fmt.Errorf("volume validation failed: no such namespace %q", vol.Namespace)
}
// validate any update we're making
var existing *structs.HostVolume
if vol.ID != "" {
existing, err = snap.HostVolumeByID(nil, vol.Namespace, vol.ID, true)
if err != nil {
return nil, err // should never hit, bail out
}
if existing == nil {
return nil, fmt.Errorf("cannot update volume %q: volume does not exist", vol.ID)
}
err = vol.ValidateUpdate(existing)
if err != nil {
return existing, fmt.Errorf("validating volume %q update failed: %v", vol.ID, err)
}
}
return existing, nil
}
// validateVolumeForState ensures that any references to node IDs or node pools are valid
func (v *HostVolume) validateVolumeForState(vol *structs.HostVolume, snap *state.StateSnapshot) error {
var poolFromExistingNode string
if vol.NodeID != "" {
node, err := snap.NodeByID(nil, vol.NodeID)
if err != nil {
return err // should never hit, bail out
}
if node == nil {View on GitHub (pinned to 482b49bf1a)
Solutions
- Clear the ID field to perform a fresh create instead of an update.
- Recreate the volume with the original ID if it was deleted unintentionally.
- Confirm the volume exists in the target namespace (`nomad volume status <id>`).
- Re-fetch current volume IDs from the API instead of caching them in automation.
Example fix
// before
vol := &nomad.HostVolume{ ID: "3f2a...", Name: "web-data" } // ID not in state
// after (intent: create new volume)
vol := &nomad.HostVolume{ Name: "web-data" } // omit ID Defensive patterns
Strategy: validation
Validate before calling
if vol.ID != "" {
_, _, err := client.HostVolumes().Get(vol.Namespace, vol.ID, nil)
if err != nil { return fmt.Errorf("volume %q not found; clear ID to create", vol.ID) }
} Type guard
func volumeExists(id, ns string, client *api.Client) bool {
v, _, err := client.HostVolumes().Get(ns, id, nil)
return err == nil && v != nil
} Try / catch
if strings.Contains(err.Error(), "volume does not exist") {
// decide: drop ID to create anew, or recreate the deleted volume
} Prevention
- Fetch fresh volume IDs from the API rather than caching
- Only set ID for genuine updates
- Track volume deletions in automation state
- Scope IDs to the correct cluster/namespace
When it happens
Trigger: Calling Create or Register with args.Volume.ID set to an ID that does not exist in the target namespace — e.g. updating a deleted volume, or a UUID from a different cluster/namespace.
Common situations: Automation pipelines holding stale volume IDs after deletion; cross-namespace moves without changing the ID; copy-pasted specs from other environments; CI re-running against a cleaned state store.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- node %q does not exist
- node pool %q does not exist
- no such volume: %s
- variable not found
- ErrPluginNotExists
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f3db705b8039317f.
Report an issue: GitHub.