The Add to cart button on a scooter stayed dead. The shopper had picked Royal Blue, the chip was highlighted, and the button refused to enable. Every weight-based product on a different store worked perfectly.
Two spellings of the same choice
WooCommerce’s Store API describes a variable product’s choices in two places. The attribute lists its terms as display labels:
{ "name": "Color", "terms": [{ "name": "Royal Blue" }] }
Each variation records the same choice as a slug:
{ "id": 166571, "attributes": [{ "name": "Color", "value": "royal-blue" }] }
We were matching the shopper’s pick against the variation values directly. “Royal Blue” is not “royal-blue”, so nothing ever matched, and the button had no variation id to send.
Why weights hid it
The other store sells by weight. Its terms are 500ml and 1000ml, and the slug of 500ml is 500ml. Identical in both alphabets. Every test passed, on every product, because no value in that catalogue contained a capital letter or a space.
That is the uncomfortable part. The tests were not weak; the data was. A bug can hide behind a catalogue that happens not to exercise it, and the only defence is a fixture that deliberately does. Ours now compares a label-against-slug pair alongside the identical-spelling case that always worked.
The fix
Normalise both sides before comparing:
const slug = (s) => (s || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
Three lines, once the cause was known. Finding it took a colour catalogue.
While we were in there
A variable product cannot be added to a WooCommerce cart by its parent id at all. The Store API
answers Missing attributes for variable product. Any integration that puts products in a cart needs
the variation’s own id, and if yours has only ever been tested against simple products, it will fail
the first time a customer picks a size.