hashicorp/nomad · error

volume not found: %s

Error message

volume not found: %s

What it means

Returned by StateStore.CSIVolumeClaim when the volume row for the given namespace+id simply does not exist (txn.First returned nil). It means a claim (mount/unmount) is being requested against a CSI volume that was deregistered or never registered in this cluster. The %s is the requested volume ID.

Source

Thrown at nomad/state/state_store.go:2879

		return nil, fmt.Errorf("volume lookup failed: %v", err)
	}

	ws.Add(iter.WatchCh())

	return iter, nil
}

// CSIVolumeClaim updates the volume's claim count and allocation list
func (s *StateStore) CSIVolumeClaim(index uint64, now int64, namespace, id string, claim *structs.CSIVolumeClaim) error {
	txn := s.db.WriteTxnMsgT(structs.CSIVolumeClaimRequestType, index)
	defer txn.Abort()

	row, err := txn.First(TableCSIVolumes, "id", namespace, id)
	if err != nil {
		return fmt.Errorf("volume lookup failed: %s: %v", id, err)
	}
	if row == nil {
		return fmt.Errorf("volume not found: %s", id)
	}

	orig, ok := row.(*structs.CSIVolume)
	if !ok {
		return fmt.Errorf("volume row conversion error")
	}

	var alloc *structs.Allocation
	if claim.State == structs.CSIVolumeClaimStateTaken {
		alloc, err = s.allocByIDImpl(txn, nil, claim.AllocationID)
		if err != nil {
			s.logger.Error("AllocByID failed", "error", err)
			return fmt.Errorf(structs.ErrUnknownAllocationPrefix)
		}
		if alloc == nil {
			s.logger.Error("AllocByID failed to find alloc", "alloc_id", claim.AllocationID)
		}
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Run nomad volume status to confirm the volume exists in the expected namespace
  2. Re-register the volume (nomad volume register or dynamic creation) if it was deleted
  3. Fix the job's volume block: correct id and namespace to match an existing volume
  4. Stop/redo allocations stuck referencing the deleted volume

Example fix

// before: job references a deregistered volume
volume "missing-vol" { type = "csi" source = "old-ebs-vol" }
// after: register the volume first, then reference it
# nomad volume register -namespace=default ./ebs-vol.hcl
volume "missing-vol" { type = "csi" source = "ebs-vol" }
Defensive patterns

Strategy: validation

Validate before calling

// guard before claiming
vol, _, err := api.CSIVolumesByID(nil, namespace, volumeID)
if err != nil {
    return err
}
if vol == nil {
    return fmt.Errorf("volume %q not found in namespace %q; register it first", volumeID, namespace)
}

Type guard

func volumeExists(vol *api.CSIVolume, err error) bool { return err == nil && vol != nil }

Try / catch

err := api.CSIVolumeClaim(&structs.CSIVolumeClaimRequest{VolumeID: id, Namespace: ns})
if err != nil && strings.Contains(err.Error(), "volume not found") {
    // volume deregistered or wrong namespace: re-register or fix the job spec
}

Prevention

When it happens

Trigger: CSIVolumeClaim called with an id/namespace combination absent from the state store — e.g. the volume was deregistered between the job submission and the alloc claiming it, or the namespace in the claim does not match where the volume lives.

Common situations: Volume deleted via nomad volume delete while jobs still reference it; job spec references a volume registered in a different namespace; ACL/namespace mismatch in multitenant clusters; stale job referencing volumes from a purged cluster.

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/861918773ae8b9f0. Report an issue: GitHub.