hashicorp/nomad · error
missing volume ID
Error message
missing volume ID
What it means
This error is returned by ControllerValidateCapabilities in the CSI client wrapper when the request's ExternalID field is empty. The library refuses to send a gRPC ValidateVolumeCapabilities call to the CSI controller plugin without a volume ID, because the plugin cannot identify which volume to validate and would return an unhelpful generic error. It is a fail-fast precondition check on the client side.
Source
Thrown at plugins/csi/client.go:376
// checkpointed. we'll return an error so the caller can log it for
// diagnostic purposes.
err = fmt.Errorf("%w: volume %q or node %q could not be found: %v",
structs.ErrCSIClientRPCIgnorable, req.ExternalID, req.NodeID, err)
case codes.Internal:
err = fmt.Errorf("controller plugin returned an internal error, check the plugin allocation logs for more information: %v", err)
}
return nil, err
}
return &ControllerUnpublishVolumeResponse{}, nil
}
func (c *client) ControllerValidateCapabilities(ctx context.Context, req *ControllerValidateVolumeRequest, opts ...grpc.CallOption) error {
if err := c.ensureConnected(ctx); err != nil {
return err
}
if req.ExternalID == "" {
return fmt.Errorf("missing volume ID")
}
if req.Capabilities == nil {
return fmt.Errorf("missing Capabilities")
}
creq := req.ToCSIRepresentation()
resp, err := c.controllerClient.ValidateVolumeCapabilities(ctx, creq, opts...)
if err != nil {
code := status.Code(err)
switch code {
case codes.NotFound:
err = fmt.Errorf("volume %q could not be found: %v", req.ExternalID, err)
case codes.Internal:
err = fmt.Errorf("controller plugin returned an internal error, check the plugin allocation logs for more information: %v", err)
}
return err
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Set req.ExternalID to the CSI volume ID from the storage provider (e.g. the ID returned by ControllerCreateVolume or listed by the plugin) before calling ControllerValidateCapabilities.
- Check where the volume ID was sourced from (volume registration, Nomad volume spec's external_id, provider console/API) and fix the empty source value.
- Add a caller-side check that the volume ID is non-empty and log the request construction path to find where it was lost.
Example fix
// before
req := &csi.ControllerValidateVolumeRequest{}
err := client.ControllerValidateCapabilities(ctx, req)
// after
if volume.ExternalID == "" {
return fmt.Errorf("volume %q has no external ID; re-register the volume", volume.Name)
}
req := &csi.ControllerValidateVolumeRequest{ExternalID: volume.ExternalID}
err := client.ControllerValidateCapabilities(ctx, req) Defensive patterns
Strategy: validation
Validate before calling
func validateVolumeReq(req *csi.ControllerValidateVolumeRequest) error {
if req == nil || req.ExternalID == "" {
return fmt.Errorf("ControllerValidateVolumeRequest.ExternalID must be set")
}
return nil
} Type guard
func hasExternalID(req *csi.ControllerValidateVolumeRequest) bool {
return req != nil && strings.TrimSpace(req.ExternalID) != ""
} Prevention
- Always derive ExternalID from a checked source (e.g. the ControllerCreateVolumeResponse) and error out at request-construction time if empty.
- Validate volume registration state (nomad volume status) before issuing controller RPCs.
- Add unit tests covering zero-value request structs.
When it happens
Trigger: Calling client.ControllerValidateCapabilities with a *ControllerValidateVolumeRequest whose ExternalID field is the empty string. Typically happens when the caller obtained the volume ID from a failed lookup, an unset variable/field, or constructed the request without populating ExternalID.
Common situations: Volume registration state was lost or never populated so the stored external volume ID is empty; a Nomad volume spec omitted the required external ID; automation scripting built the request struct and forgot to set ExternalID; an upstream API returned an empty ID after a failed create that the caller did not check.
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
- CSI.ControllerAttachVolume: VolumeID is required
- CSI.ControllerAttachVolume: ClientCSINodeID is required
- CSI.ControllerDetachVolume: VolumeID is required
- CSI.ControllerDetachVolume: ClientCSINodeID is required
- CSI.NodeDetachVolume: PluginID is required
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/48f7c6080c231c5d.
Report an issue: GitHub.