hashicorp/nomad · error

volume capability validation failed: %v

Error message

volume capability validation failed: %v

What it means

After a successful ValidateVolumeCapabilities response, the CSI spec lets the plugin echo back the capabilities it confirmed. This client compares each requested capability against the confirmed set using compareCapabilities, and returns this error when any requested capability does not match what the volume actually supports. It means the volume exists but cannot provide the access mode or access type requested.

Source

Thrown at plugins/csi/client.go:412

	}

	if resp.Message != "" {
		// this should only ever be set if Confirmed isn't set, but
		// it's not a validation failure.
		c.logger.Debug(resp.Message)
	}

	// The protobuf accessors below safely handle nil pointers.
	// The CSI spec says we can only assert the plugin has
	// confirmed the volume capabilities, not that it hasn't
	// confirmed them, so if the field is nil we have to assume
	// the volume is ok.
	confirmedCaps := resp.GetConfirmed().GetVolumeCapabilities()
	if confirmedCaps != nil {
		for _, requestedCap := range creq.VolumeCapabilities {
			err := compareCapabilities(requestedCap, confirmedCaps)
			if err != nil {
				return fmt.Errorf("volume capability validation failed: %v", err)
			}
		}
	}

	return nil
}

func (c *client) ControllerCreateVolume(ctx context.Context, req *ControllerCreateVolumeRequest, opts ...grpc.CallOption) (*ControllerCreateVolumeResponse, error) {
	if err := c.ensureConnected(ctx); err != nil {
		return nil, err
	}

	err := req.Validate()
	if err != nil {
		return nil, err
	}
	creq := req.ToCSIRepresentation()
	resp, err := c.controllerClient.CreateVolume(ctx, creq, opts...)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Align the requested capabilities in the volume spec with what the volume supports — check the plugin's documented access modes/attachment modes and update volume_capabilities accordingly.
  2. Re-create or resize/convert the volume on the storage backend so it supports the requested access mode, or create a new volume with matching capabilities.
  3. Check the plugin's resp.Message and compareCapabilities output in the error text to see exactly which capability differs, then adjust that single field.
  4. If a plugin upgrade introduced stricter confirmation, update client volume specs to match the plugin's confirmed capabilities or pin the older plugin version.

Example fix

// before
volume {
  type            = "csi"
  attachment_mode = "file-system"
  access_mode     = "multi-node-single-writer"  # unsupported by this plugin
}

// after
volume {
  type            = "csi"
  attachment_mode = "file-system"
  access_mode     = "single-node-writer"  # matches volume's confirmed capability
}
Defensive patterns

Strategy: validation

Validate before calling

err := csi.ControllerValidateCapabilities(ctx, &csi.ControllerValidateVolumeRequest{
    ExternalID:   volID,
    Capabilities: wantCaps,
})
// compare wantCaps against plugin-advertised capabilities from
// ControllerGetCapabilities before committing the volume to the spec

Type guard

func capsMatch(want, confirmed []*csi.VolumeCapability) bool {
    for _, w := range want {
        if compareCapabilities(w, confirmed) != nil {
            return false
        }
    }
    return true
}

Try / catch

if err := client.ControllerValidateCapabilities(ctx, req); err != nil {
    if strings.Contains(err.Error(), "capability validation failed") {
        return fmt.Errorf("spec declares unsupported capabilities: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ControllerValidateCapabilities where req.Capabilities asks for something the volume cannot deliver — e.g. requesting MULTI_NODE_READER_ONLY when the volume was created SINGLE_NODE_WRITER, a mismatched filesystem type, or a plugin that sets resp.Message/confirmed capabilities that differ from the request.

Common situations: A Nomad volume spec declares capabilities (access_mode/attachment_mode) that the storage backend volume does not support; the volume was created with different capabilities than the task group requests; a plugin upgrade began confirming capabilities and exposed a pre-existing spec mismatch; multiple task groups request conflicting access modes on the same volume.

Related errors


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