hashicorp/nomad · error

requested capabilities not compatible with volume %q: %v

Error message

requested capabilities not compatible with volume %q: %v

What it means

This error is returned by the CSI client's ControllerExpandVolume when the storage plugin's controller responds with gRPC status InvalidArgument. It means the volume capabilities (access mode, access type, filesystem) in the expansion request were rejected as incompatible with the existing volume on the storage backend. The library maps the raw gRPC status code to this human-readable message so callers can distinguish capability mismatches from other expansion failures. The underlying plugin error text is appended for diagnostics.

Source

Thrown at plugins/csi/client.go:531

	}
	return err
}

func (c *client) ControllerExpandVolume(ctx context.Context, req *ControllerExpandVolumeRequest, opts ...grpc.CallOption) (*ControllerExpandVolumeResponse, error) {
	if err := req.Validate(); err != nil {
		return nil, err
	}
	if err := c.ensureConnected(ctx); err != nil {
		return nil, err
	}

	exReq := req.ToCSIRepresentation()
	resp, err := c.controllerClient.ControllerExpandVolume(ctx, exReq, opts...)
	if err != nil {
		code := status.Code(err)
		switch code {
		case codes.InvalidArgument:
			return nil, fmt.Errorf(
				"requested capabilities not compatible with volume %q: %v",
				req.ExternalVolumeID, err)
		case codes.NotFound:
			err = fmt.Errorf("volume %q could not be found: %v", req.ExternalVolumeID, err)
		case codes.FailedPrecondition:
			err = fmt.Errorf("volume %q cannot be expanded online: %v", req.ExternalVolumeID, err)
		case codes.OutOfRange:
			return nil, fmt.Errorf(
				"unsupported capacity_range for volume %q: %v", req.ExternalVolumeID, err)
		case codes.Internal:
			err = fmt.Errorf("controller plugin returned an internal error, check the plugin allocation logs for more information: %v", err)
		default:
			err = fmt.Errorf("controller plugin returned an error: %v", err)
		}
		return nil, err
	}

	return &ControllerExpandVolumeResponse{

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the appended gRPC error detail to identify which capability field was rejected.
  2. Ensure the ControllerExpandVolumeRequest capability matches the volume's original creation capabilities exactly (access mode, mount volume/filesystem).
  3. Re-create the volume with the desired capabilities instead of expanding an incompatible one.
  4. Check the CSI plugin version/docs for capability restrictions on online expansion.

Example fix

// before
req := &csi.ControllerExpandVolumeRequest{
    ExternalVolumeID: id,
    CapacityRange:    &csi.CapacityRange{RequiredBytes: newSize},
    // capability omitted or changed from creation time
}
// after
req := &csi.ControllerExpandVolumeRequest{
    ExternalVolumeID: id,
    CapacityRange:    &csi.CapacityRange{RequiredBytes: newSize},
    VolumeCapability: originalCreationCapability, // same access mode + fs as at creation
}
Defensive patterns

Strategy: try-catch

Validate before calling

if req.CapacityRange == nil || req.CapacityRange.RequiredBytes <= currentVol.CapacityBytes {
    return fmt.Errorf("required bytes must be greater than current size %d", currentVol.CapacityBytes)
}
// ensure capability matches creation-time capability
if !reflect.DeepEqual(req.VolumeCapability, creationSpec.VolumeCapability) {
    return fmt.Errorf("expansion capability must match original volume capability")
}

Type guard

func isInvalidArgumentErr(err error) bool {
    if err == nil { return false }
    return strings.Contains(err.Error(), "requested capabilities not compatible with volume")
}

Try / catch

resp, err := client.ControllerExpandVolume(ctx, req)
if err != nil {
    if strings.Contains(err.Error(), "requested capabilities not compatible with volume") {
        // fix capability in the volume spec to match creation-time capability
        return fmt.Errorf("fix volume capability: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ControllerExpandVolume (e.g. via Nomad's volume expansion path) with a ControllerExpandVolumeRequest whose VolumeCapability does not match how the volume was originally created, and the CSI plugin replies with codes.InvalidArgument.

Common situations: Changing the access mode (e.g. MULTI_NODE_READER_ONLY to SINGLE_NODE_WRITER) or filesystem type between volume creation and expansion; a plugin upgrade that changed capability validation; running expansion against a volume created by a different driver or with different mount options.

Related errors


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