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
- Populate the Claim struct with at least the AllocationID (and NodeID if known) of the claim being released.
- If the intent was to drop the whole volume registration, use `nomad volume delete`/deregister instead of unpublish.
- 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
- Always include the claim's AllocationID (and NodeID when known) in unpublish payloads.
- Use `nomad volume detach`/client helpers instead of hand-built HTTP bodies.
- Distinguish unpublish (release a claim) from delete (remove registration) in tooling.
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
- missing secret ID
- CSI.ControllerValidateVolume: VolumeID is required
- CSI.ControllerValidateVolume: PluginID is required
- CSI.ControllerAttachVolume: VolumeID is required
- CSI.ControllerAttachVolume: ClientCSINodeID is required
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/b59aca8a937a3fd0.
Report an issue: GitHub.