hashicorp/nomad · error

CSI.ControllerValidateVolume: %v

Error message

CSI.ControllerValidateVolume: %v

What it means

ControllerValidateVolume fails when req.ToCSIRequest() cannot convert the Nomad-side request into a CSI protocol request (validating required fields such as volume ID, plugin ID, capabilities). The error is prefixed with the method name and returned unwrapped (not retryable).

Source

Thrown at client/csi_endpoint.go:64

		return errors.New("CSI.ControllerValidateVolume: VolumeID is required")
	}

	if req.PluginID == "" {
		return errors.New("CSI.ControllerValidateVolume: PluginID is required")
	}

	plugin, err := c.findControllerPlugin(req.PluginID)
	if err != nil {
		// the server's view of the plugin health is stale, so let it know it
		// should retry with another controller instance
		return fmt.Errorf("CSI.ControllerValidateVolume: %w: %v",
			nstructs.ErrCSIClientRPCRetryable, err)
	}
	defer plugin.Close()

	csiReq, err := req.ToCSIRequest()
	if err != nil {
		return fmt.Errorf("CSI.ControllerValidateVolume: %v", err)
	}

	ctx, cancelFn := c.requestContext()
	defer cancelFn()

	// CSI ValidateVolumeCapabilities errors for timeout, codes.Unavailable and
	// codes.ResourceExhausted are retried; all other errors are fatal.
	err = plugin.ControllerValidateCapabilities(ctx, csiReq,
		grpc_retry.WithPerRetryTimeout(CSIPluginRequestTimeout),
		grpc_retry.WithMax(3),
		grpc_retry.WithBackoff(grpc_retry.BackoffExponential(100*time.Millisecond)))
	if err != nil {
		return fmt.Errorf("CSI.ControllerValidateVolume: %v", err)
	}
	return nil
}

// ControllerAttachVolume is used to attach a volume from a CSI Cluster to

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the underlying %v cause to find which required request field failed validation
  2. Fix the volume registration/job volume block so required fields (volume id, plugin id, capabilities) are populated
  3. Re-submit the volume registration or CSI RPC with a well-formed request
  4. Check server/client Nomad versions for skew causing struct incompatibility

Example fix

// before
req := &structs.ClientCSIControllerValidateVolumeRequest{PluginID: "aws-efs"} // VolumeID empty
// after
req := &structs.ClientCSIControllerValidateVolumeRequest{PluginID: "aws-efs", VolumeID: volID, VolumeContext: ctx, Caps: caps}
Defensive patterns

Strategy: validation

Validate before calling

func validateControllerValidateReq(req *structs.ClientCSIControllerValidateVolumeRequest) error {
    if req.PluginID == "" { return errors.New("PluginID required") }
    if req.VolumeID == "" { return errors.New("VolumeID required") }
    if len(req.Caps) == 0 { return errors.New("capabilities required") }
    return nil
}

Try / catch

if err := validateControllerValidateReq(req); err != nil {
    // fix request fields before the RPC; this error is fatal, not retryable
    return fmt.Errorf("invalid request: %w", err)
}

Prevention

When it happens

Trigger: Calling ControllerValidateVolume with a request struct missing required fields, so ToCSIRequest returns a validation error before any gRPC call to the plugin.

Common situations: A volume registration with malformed/empty capability or volume fields; a server bug after a structs schema change (version skew between server and client); hand-crafted RPCs in tests or custom tooling.

Related errors


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