Why a variation without a SKU holds the product back
In WooCommerce the variation is the sellable unit. It is the row that carries stock, the line on the order, the item in the shopping feed and the code the warehouse picks. When its SKU is empty, WooCommerce quietly shows the parent's SKU instead, and everything downstream loses the ability to tell siblings apart.
- Stock and orders blur together. Sales reports, packing slips and CSV exports list the parent code for every variation, so a sold-out medium and an overstocked large look like the same product.
- Feeds and integrations reject or merge them. Google Merchant Center, marketplaces and accounting or ERP connectors identify items by SKU; variations without one are dropped, collapsed into a single listing, or flagged as duplicates.
- Reimports create duplicates. Importers and sync tools match on SKU. A variation with no code cannot be matched on the next import, so it is created again instead of updated.
- Search and support get harder. Staff searching wp-admin or a helpdesk for a variation code find nothing, and a customer quoting a SKU from a packing slip is quoting the whole family.
How to find variations without a SKU manually
Variations are rows in wp_posts with the type
product_variation, and their SKU lives in
wp_postmeta under _sku. This WP-CLI query
lists published variations of published variable products whose SKU is
missing or empty, next to the parent's title and SKU:
wp db query "SELECT v.ID, p.post_title AS parent, ps.meta_value AS parent_sku FROM wp_posts v JOIN wp_posts p ON p.ID = v.post_parent AND p.post_type = 'product' AND p.post_status = 'publish' LEFT JOIN wp_postmeta vs ON vs.post_id = v.ID AND vs.meta_key = '_sku' LEFT JOIN wp_postmeta ps ON ps.post_id = p.ID AND ps.meta_key = '_sku' WHERE v.post_type = 'product_variation' AND v.post_status = 'publish' AND (vs.meta_value IS NULL OR vs.meta_value = '') ORDER BY p.post_title, v.ID LIMIT 50;"
Adjust the table prefix if yours isn't wp_. To see which
options each variation carries, join wp_postmeta again on
keys starting with attribute_.
The list is the easy part. The query names variations by ID, so someone still has to open each one to learn whether it is the red small or the blue large, decide what code the store's pattern implies, check that the code is not already taken by another product or variation, and type it in. Do that once and the next import of a variable product with blank variation SKUs starts the job over.
How CatalogLift finds it
Every scan walks the published variations of published variable products in the synced catalog and reads each variation's SKU as it came from WooCommerce. A variation whose SKU is missing or empty becomes a finding at high severity, with the parent product's title and the variation's own attributes spelled out as evidence, so you know which sibling you are looking at without opening it.
Each finding also carries a suggested SKU where one can be offered safely: the parent's SKU followed by the variation's option values, uppercased and reduced to letters, digits and hyphens. CatalogLift checks that the candidate is not already used by any product or variation in the store and that no sibling in the same scan would claim the same code; a variation with an option set to Any, or a parent without a SKU of its own, gets no suggestion at all, because a prefilled duplicate is worse than an empty box.
There is no AI on this path. You confirm the suggestion or type your own code inside CatalogLift and approve it. Nothing is written before that decision; on it, CatalogLift writes the SKU to WooCommerce and the next scan verifies the variation carries it. Because CatalogLift keeps watching, an import that adds variations without codes shows up as a fresh finding instead of a quiet regression, and the first scan costs nothing and needs no card.