hashicorp/nomad · error

missing volume claim

Error message

missing volume claim

What it means

CSIVolume.Unpublish rejects the request because the CSIVolumeUnpublishRequest has a nil Claim. The claim identifies which allocation/node/read-write state is being released, so without it Nomad cannot checkpoint or detach anything. This is request validation that happens after ACL authorization but before any state mutation.

Source

Thrown at nomad/csi_endpoint.go:713

		return structs.ErrPermissionDenied
	}

	defer metrics.MeasureSince([]string{"nomad", "volume", "unpublish"}, time.Now())

	allowVolume := acl.NamespaceValidator(acl.NamespaceCapabilityCSIMountVolume)
	aclObj, err := v.srv.ResolveACL(args)
	if err != nil {
		return err
	}
	if err := v.authorizeUnpublish(aclObj, args, allowVolume); err != nil {
		return err
	}

	if args.VolumeID == "" {
		return fmt.Errorf("missing volume ID")
	}
	if args.Claim == nil {
		return fmt.Errorf("missing volume claim")
	}

	ws := memdb.NewWatchSet()
	state := v.srv.fsm.State()
	vol, err := state.CSIVolumeByID(ws, args.Namespace, args.VolumeID)
	if err != nil {
		return err
	}
	if vol == nil {
		return fmt.Errorf("no such volume")
	}

	claim := args.Claim

	// we need to checkpoint when we first get the claim to ensure we've set the
	// initial "past claim" state, otherwise a client that unpublishes (skipping
	// the node unpublish b/c it's done that work) fail to get written if the
	// controller unpublish fails.

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Populate the Claim struct with at least the AllocationID (and NodeID if known) of the claim being released.
  2. If the intent was to drop the whole volume registration, use `nomad volume delete`/deregister instead of unpublish.
  3. Add a pre-send check that both VolumeID and Claim are set.

Example fix

// before
body := fmt.Sprintf(`{"VolumeID": %q}`, volID)
// after
body := fmt.Sprintf(`{"VolumeID": %q, "Claim": {"AllocationID": %q, "NodeID": %q}}`, volID, allocID, nodeID)
Defensive patterns

Strategy: validation

Validate before calling

if req.Claim == nil || req.Claim.AllocationID == "" {
    return fmt.Errorf("Claim (with AllocationID) must be set before calling Unpublish")
}

Try / catch

if err != nil && strings.Contains(err.Error(), "missing volume claim") {
    // populate the claim and resend
}

Prevention

When it happens

Trigger: Raised when args.Claim == nil in Unpublish: the caller supplied the VolumeID but omitted the CSIVolumeClaim (Mode/NodeID/AllocationID/ExternalNodeID) — typically a hand-built HTTP JSON body missing the "claim" object or a Go struct literal that only sets VolumeID.

Common situations: Custom automation that unpublishes volumes via the raw HTTP API constructing incomplete bodies; unmarshalling payload JSON where nested claim fields were misnamed; scripts copied from the deregister (not unpublish) flow.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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