hashicorp/nomad · error

CSI.ControllerCreateSnapshot: %v

Error message

CSI.ControllerCreateSnapshot: %v

What it means

CSI.ControllerCreateSnapshot also wraps the error from req.ToCSIRequest() with this message. ToCSIRequest converts the Nomad RPC request into a CSI protobuf request; failure here means the request itself could not be converted, e.g. required fields are missing or invalid before any plugin is contacted.

Source

Thrown at client/csi_endpoint.go:383

	return nil
}

func (c *CSI) ControllerCreateSnapshot(req *structs.ClientCSIControllerCreateSnapshotRequest, resp *structs.ClientCSIControllerCreateSnapshotResponse) error {
	defer metrics.MeasureSince([]string{"client", "csi_controller", "create_snapshot"}, time.Now())

	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.ControllerCreateSnapshot: %w: %v",
			nstructs.ErrCSIClientRPCRetryable, err)
	}
	defer plugin.Close()

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

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

	// CSI ControllerCreateSnapshot errors for timeout, codes.Unavailable and
	// codes.ResourceExhausted are retried; all other errors are fatal.
	cresp, err := plugin.ControllerCreateSnapshot(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.ControllerCreateSnapshot: %v", err)
	}

	if cresp == nil || cresp.Snapshot == nil {
		c.c.logger.Warn("plugin did not return error or snapshot; this is a bug in the plugin and should be reported to the plugin author")
		return fmt.Errorf("CSI.ControllerCreateSnapshot: plugin did not return error or snapshot")

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check the snapshot request carries a valid source volume ID / secret fields
  2. Re-run `nomad volume status` to confirm the source volume is registered with complete data
  3. Align Nomad server and client versions so request schemas match
  4. Retry the nomad volume snapshot create command with corrected arguments

Example fix

// before
nomad volume snapshot create "" my-snap  # empty volume ID
// after
nomad volume snapshot create web-data my-snap
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the source volume is registered and has an external ID before snapshotting:
vol, err := client.Volumes().Get(ctx, "web-data")
if err != nil || vol.ID == "" {
    // cannot build a valid CSI CreateSnapshotRequest
    return fmt.Errorf("source volume missing: %w", err)
}

Try / catch

// Detect the wrapping prefix to distinguish conversion failures
if err := c.ControllerCreateSnapshot(req, resp); err != nil {
    var convErr error
    if strings.HasPrefix(err.Error(), "CSI.ControllerCreateSnapshot:") {
        convErr = err // inspect message for the underlying cause
    }
}

Prevention

When it happens

Trigger: req.ToCSIRequest() returns an error while building the CSI CreateSnapshotRequest from the ClientCSIControllerCreateSnapshotRequest, typically because source volume ID or other required fields are empty/invalid.

Common situations: Snapshot requests referencing a volume whose CSI metadata is incomplete; server-side request construction passing an unset SourceVolumeID; older Nomad server talking to newer client (or vice versa) with divergent request schemas.

Related errors


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