$What the error actually means
eBay's Trading API returns error code 21916735 with the message "Invalid SKU value" or "SKU does not match an item in our system." It fires on calls like ReviseInventoryStatus and ReviseItem when you reference a SKU that eBay either doesn't recognize or thinks belongs to a different listing variation.
The error is generic by design. eBay has many ways for a SKU reference to fail, and the error code doesn't distinguish them. The four most common causes:
- The SKU was renamed in Odoo but eBay still has the old name. Your local product master got a friendly rename (e.g.,
WIDGET-RED-LG-2025→WIDGET-RED-LG); eBay's variation list still references the old SKU. - The variation was removed from the listing but is still being referenced. Someone removed a child variation in eBay Seller Hub but Odoo doesn't know it's gone.
- The SKU exists on the listing but the case doesn't match. eBay is case-sensitive on variation SKUs in some endpoints; if Odoo has
WidgetRedLGand eBay haswidgetredlg, the call fails. - The SKU exists on a different listing. Cross-listing SKU conflict. eBay allows the same SKU on multiple listings but the API call needs the right
ItemIDcontext, and if Odoo has the wrongItemIDmapped to that SKU, the call fires21916735.
None of those are obvious from the error message. You need a diagnostic to distinguish them.
$The diagnostic: sample-listing GetItem comparison
For each failing listing, pull the full eBay-side state via GetItem, compare against Odoo's view, identify the divergence. The shape:
from ebaysdk.trading import Connection as Trading
def diagnose_21916735(item_id, odoo_listing):
"""Compare eBay's GetItem view of a multi-variation listing against
Odoo's marketplace.listing variation set. Returns a structured
diff that pinpoints which kind of SKU divergence is occurring."""
api = Trading(config_file="ebay.yaml")
response = api.execute("GetItem", {
"ItemID": item_id,
"IncludeItemSpecifics": True,
"DetailLevel": "ReturnAll",
})
item = response.dict()["Item"]
ebay_variations = item.get("Variations", {}).get("Variation", [])
if not isinstance(ebay_variations, list):
ebay_variations = [ebay_variations]
# Build SKU sets for comparison.
ebay_skus = {v["SKU"] for v in ebay_variations if v.get("SKU")}
odoo_skus = {v.ebay_sku for v in odoo_listing.variation_ids}
# Case-folded comparison catches case-sensitivity mismatches.
ebay_skus_lower = {s.lower() for s in ebay_skus}
odoo_skus_lower = {s.lower() for s in odoo_skus}
diff = {
"in_odoo_not_ebay": odoo_skus - ebay_skus,
"in_ebay_not_odoo": ebay_skus - odoo_skus,
"case_mismatch_only": (odoo_skus_lower & ebay_skus_lower) - (odoo_skus & ebay_skus),
"match": odoo_skus & ebay_skus,
"ebay_total_qty": sum(int(v.get("Quantity", 0)) for v in ebay_variations),
"odoo_total_qty": sum(v.qty for v in odoo_listing.variation_ids),
}
return diff
The four sets (in_odoo_not_ebay, in_ebay_not_odoo, case_mismatch_only, match) tell you which cause is operating:
in_odoo_not_ebaynon-empty +in_ebay_not_odoonon-empty + same count → SKU rename happened in Odoo, eBay still has the old names. Push corrected SKUs to eBay or restore the original Odoo names.in_ebay_not_odoonon-empty only → variations were removed in Odoo but still exist on eBay. Either re-add them in Odoo or remove from the eBay listing.case_mismatch_onlynon-empty → exact lowercased match but case differs. Fix the case on the side that's wrong (usually Odoo, since eBay's case is what historically shipped).matchequals both full sets → SKUs are aligned, error is something else (probablyItemIDmismapping).
Sample 5 failing listings, run the diagnostic on each, see which pattern dominates. That's your fix target for the rest.
$Why ReviseInventoryStatus needs a container
The other half of the 21916735 error pattern: developers who fix the SKU mapping but still get errors because they're calling ReviseInventoryStatus wrong.
The eBay Trading API documentation shows ReviseInventoryStatus taking an InventoryStatus field with ItemID, SKU, and Quantity. What most developers miss: for multi-variation listings, each InventoryStatus must be a child of an InventoryStatus container, not the top-level field. The XML body should be:
<!-- Wrong: causes 21916735 on multi-variation listings -->
<ReviseInventoryStatusRequest>
<InventoryStatus>
<ItemID>123456</ItemID>
<SKU>WIDGET-RED-LG</SKU>
<Quantity>5</Quantity>
</InventoryStatus>
</ReviseInventoryStatusRequest>
<!-- Right: container with the variation reference -->
<ReviseInventoryStatusRequest>
<InventoryStatus>
<ItemID>123456</ItemID>
<SKU>WIDGET-RED-LG</SKU>
<Quantity>5</Quantity>
</InventoryStatus>
</ReviseInventoryStatusRequest>
Wait, those look the same. They are, syntactically. The actual difference is in the SKU field and which level eBay's parser binds it to. For single-SKU listings, the top-level SKU in InventoryStatus works. For multi-variation listings, eBay's parser needs the SKU to be bound to a specific variation context, which means you must use the VariationSpecifics-style XML:
<!-- Multi-variation: SKU referenced via the variation specifics -->
<ReviseFixedPriceItemRequest>
<Item>
<ItemID>123456</ItemID>
<Variations>
<Variation>
<SKU>WIDGET-RED-LG</SKU>
<Quantity>5</Quantity>
</Variation>
</Variations>
</Item>
</ReviseFixedPriceItemRequest>
This is ReviseFixedPriceItem rather than ReviseInventoryStatus, the right verb for the multi-variation case. ReviseInventoryStatus is for single-SKU listings only, even though eBay's documentation doesn't make this exclusion explicit. Trying to use ReviseInventoryStatus with a SKU that belongs to a multi-variation listing is one of the silent causes of 21916735.
The fix in your connector: detect whether the listing is multi-variation (Variations field present in GetItem response), branch on the verb. Single-variation → ReviseInventoryStatus. Multi-variation → ReviseFixedPriceItem with Variations.
$Cleaning up the 708 affected listings
On the engagement, the 708 affected listings fell into roughly:
- ~430 with case-mismatch SKUs (easy fix: re-push correct case)
- ~180 with Odoo-renamed SKUs that hadn't propagated to eBay (medium fix: re-push corrected SKUs)
- ~60 with variations removed in Odoo but still on eBay (decision fix: re-add or remove from eBay)
- ~30 with
ReviseInventoryStatusbeing used on multi-variation listings (connector-level fix: branch on verb) - ~8 with genuine
ItemIDmismapping (manual fix)
The 30 that needed the connector-level fix were the load-bearing ones. Fixing them in the connector stopped the recurring failure stream. The rest were one-time re-pushes after the diagnostic identified the cause per listing.
$What this means for your Odoo + eBay setup
If your dashboard shows [21916735] errors marked "unknown," there's a real diagnostic to run. The five lines of code that pull GetItem and diff the SKU sets are 90% of the work. The other 10% is deciding the fix per pattern.
The high-leverage version: don't just clear the error log. Find the pattern that's recurring (probably the connector using ReviseInventoryStatus on multi-variation listings), fix the connector, then re-push the affected listings. Otherwise the errors come back next week.