End Point

News

Welcome to End Point's blog

Ongoing observations by End Point people.

Spree Active Shipping Gem "We are unable to calculate shipping rates for the selected items." Error

I was recently working on a Spree site and setting up the Spree Active Shipping Gem along with the UPS API. For those not familiar, the Spree Active Shipping Gem interacts with various shipping APIs like UPS, USPS, and FedEx. Due to the nature of Spree – where it does so much for you, and the interaction between the Active Shipping Gem and a shipping API also being 'auto-magic', it is often difficult to debug. As I was recently undertaking the task of setting this up I found a few 'gotchas' that I hope, through this blog post, may be able to save others a lot of time.

I have found that there wasn't a lot of instruction for setting up the Active Shipping Gem and a shipping carrier API like the UPS Shipping API. Ostensibly, there isn't much to it – the Active Shipping Gem handles much of the interaction between the shipping API of choice and Spree.

First, you're going to go the Spree Active Shipping Gem GitHub repo and follow the instructions for installing the Active Shipping Gem. It is very straightforward, but do proceed in the order mentioned in the Spree Active Shipping Gem documentation as some steps depend on the successful completion of others.

Second, you're going to go to the shipper of your choice, in this case UPS, and follow their directions for using their API. I do recommend actually reading, or at least skimming, the pages and pages of documentation. Why? Because there are some important agreements explaining how the API is to be used (basically legal requirements for the UPS logo).

The Active Shipping Gem makes a call to the API, the API returns a hash of various shipping methods and prices based on the parameters you've sent it (such as shipment origin and destination), and then it automatically displays in the UI as an adjustment. How great is that?!

Well, it would be great if it all worked out exactly as planned. However, if you are running Spree 2-0-stable you may find yourself battling an unusual circumstance. Namely, Spree 2-0-stable will create your core/app/views/spree/checkout/edit.html.erb as

<% content_for :head do %>
     <%= javascript_include_tag '/states' %>
   <% end %>

This will provide the incorrect path. It is intended to hit the StatesController, so update it like so:

<% content_for :head do %>
     <%= javascript_include_tag states_url %>
   <% end %>

Now, once this correction has been made you may find that you are still having an error, "We are unable to calculate shipping rates for the selected items."

At this point Chrome Dev Tools will not show any errors. When I had this error, a number of Google searches returned results of the kind "make sure you have set up your shipping zones correctly and added shipping methods to these zones". I verified this again and again in the console, as did many others who were equally perplexed by this message on StackOverflow as well as in Google Groups, like here and here. Some got this error when they added an item to the cart that had a count_on_hand of 0 and backorderable equal to false, like you can see here at Spree GitHub issues. If a 0 count_on_hand is what is giving you this error, but you want a product to be backorderable, make sure to also check the 'Propagate All Variants' in the Spree admin as seen below. This will loop through all of the product's variants with a count_on_hand of 0, and allow them to be backorderable.

After a long while of searching and wondering, is it the API? Is it the Active Shipping Gem? Is it a blacklisted zip code? I went through and changed one setting at a time in the Spree admin until finally arriving at the source of this error for me. Missing product weight. Because UPS needs the product weight in order to calculate shipping charges, make sure this is set.

The "We are unable to calculate shipping rates for the selected items" error message is misleading. If you encounter this error after correcting the javascript_include_tag, the cause is most likely a setting in the admin. Check for how insufficient inventory is handled, missing product weights, or incorrectly setup up or non-existent shipping zones & associated methods. I hope if this error message is what brought you here that this post has saved you some time.

5 comments:

Steph Skardal said...

Matt, I expect that you should be able to debug the raw output of the UPS response in the gem source code itself. Is this something you tried? I ask this because I've had to examine the UPS response directly in the past to debug shipping errors. Also, were you able to examine the AJAX specifics using Firebug? I've always found debugging AJAX requests in Firebug to be easier than in Chrome.

Matt Galvin said...

Hey Steph,
I did not try debugging the raw output of the UPS response in the gem source code. I will give that a shot if/when the next opportunity arises. Also, thank you for the head's up on Firebug for debugging AJAX requests. In the past I've tended to stick with Chrome because that's what I'm most familiar with- but, I am always interested in learning about and using other available tools.

John Hirbour said...

"We are unable to calculate shipping rates for the selected items." is probably the most ambiguous error message in spree.

It can mean any of the following:
- you've setup zones incorrectly
- you've setup shipping_methods incorrectly
- order.shipments is empty
- product setup errors

I've gotten snagged by all of these at some point. It would be cool is spree had an option "hey I'm in development mode... display something useful" for this errror.

Last time this snagged me was because even though you have track_inventory = false you still need rows in spree_stock_items . I had loaded a bunch of product data from seed files and ignored this table.

Maybe we the "spreeple" can put together a list of "things to check" for this error...

Matt Galvin said...

Hey John!
I agree with you and thanks for sharing that. The last time this one got me me was because, for some reason, the origin address and API credentials were not saving in the Admin.

fer said...

@john comment pointed me in the right direction: even with the track_inventory = false you have to setup a default location or the corresponding spree_stock_items won't be created.

In cases this helps someone, this is the related code:

Every product contains at least the master variant and for every variant they create those stock_items

Spree::Variant#create_stock_items

StockLocation.all.each do |stock_location|
stock_location.propagate_variant(self) if stock_location.propagate_all_variants?
end
end

which goes to Spree::StockLocation#propagate_variant(variant)

self.stock_items.create!(variant: variant, backorderable: self.backorderable_default)
end

Then, at some point in the checkout they call

Spree::Stock::Order#create_proposed_shipments

which calls

Spree::Stock::Coordinator#build_packages to build the shipments, which starts with a nice

StockLocation.active.each do |stock_location|
next unless stock_location.stock_items.where(:variant_id => inventory_units.map(&:variant_id)).exists?