hashicorp/nomad · error

volume in use by allocations

Error message

volume %s in use by allocations: %v

What it means

HostVolume.Delete refuses to remove a volume that still has active allocations: if vol.Allocations is non-empty, it lists the allocation IDs in the error. Deleting would orphan running workloads using the volume, so the server blocks the write until the allocations are stopped.

Solutions

  1. Stop the jobs using the volume (`nomad job stop <job>`) and wait for their allocations to finish, then retry the delete.
  2. Run `nomad system gc` to clear stale allocations that block deletion.
  3. Purge stopped jobs (`nomad job stop -purge`) so their allocations are removed and no longer reference the volume.

Example fix

// before
nomad host volume delete my-vol          # in use by allocs [a1, a2]
// after
nomad job stop -purge my-app
nomad system gc
nomad host volume delete my-vol
Defensive patterns

Strategy: validation

Validate before calling

vol, _, err := client.HostVolumes().Info(id, nil, nil)
if err != nil { return err }
if len(vol.Allocations) > 0 {
    return fmt.Errorf("volume %s still used by %d allocations; stop jobs first", id, len(vol.Allocations))
}

Try / catch

err := client.HostVolumes().Delete(ns, id, nil)
if err != nil && strings.Contains(err.Error(), "in use by allocations") {
    // stop owning jobs, wait, GC, then retry
    stopJobsUsingVolume(id)
    client.System().GC()
    err = client.HostVolumes().Delete(ns, id, nil)
}

Prevention

When it happens

Trigger: Calling Delete while jobs still reference the volume and have running/pending allocations — e.g. deleting a volume backing a live service job, or leaked allocations from a killed job that haven't been GC'd.

Common situations: Tearing down a volume before stopping the jobs that mount it; failed jobs leaving un-GC'd allocations; users deleting by stale CLI output while a deployment is in progress.

Related errors


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

Appendix: source

Thrown at nomad/host_volume_endpoint.go:704

	snap, err := v.srv.State().Snapshot()
	if err != nil {
		return err
	}

	ns := args.RequestNamespace()
	id := args.VolumeID

	vol, err := snap.HostVolumeByID(nil, ns, id, true)
	if err != nil {
		return fmt.Errorf("could not query host volume: %w", err)
	}
	if vol == nil {
		return fmt.Errorf("no such volume: %s", id)
	}
	if len(vol.Allocations) > 0 {
		allocIDs := helper.ConvertSlice(vol.Allocations,
			func(a *structs.AllocListStub) string { return a.ID })
		return fmt.Errorf("volume %s in use by allocations: %v", id, allocIDs)
	}

	// serialize client RPC and raft write per volume ID
	index, err := v.serializeCall(vol.ID, "delete", func() (uint64, error) {
		if err := v.deleteVolume(vol); err != nil {
			if structs.IsErrUnknownNode(err) || structs.IsErrNoNodeConn(err) {
				if !args.Force {
					return 0, fmt.Errorf(
						"volume cannot be removed from unknown node without force=true")
				}
			} else {
				return 0, err
			}
		}
		_, idx, err := v.srv.raftApply(structs.HostVolumeDeleteRequestType, args)
		if err != nil {
			v.logger.Error("raft apply failed", "error", err, "method", "delete")
			return 0, err

View on GitHub (pinned to 482b49bf1a)