The one-barcode-per-variant limit is gone: a variant can now hold up to 20 typed identifiers across UPC / EAN / ISBN / GTIN / ASIN. The old barcode field keeps working, but it is deprecated. Keep reading only that field and you will never notice the other barcodes exist.
Any identifier beyond the first was pushed into metafields, tags, or an external system. Which one held what varied store by store and lived in someone's head.
ProductVariant.barcodes connection to read, and thebarcodes input to write. Declare the type and the value is validated against that standard's rules.
productSet / productVariantsBulkCreate / productVariantsBulkUpdate . All three accept the barcodes input.products and productVariants queries' barcode filter now matches any of the barcodes a variant holds. It no longer matches only the first one.Each barcode can declare a type . When declared, the value is validated against that format's character set, digit count, prefix, and check digit rules.
Values that don't match the character set, length, prefix, or check digit rules are rejected. Data quality is enforced at the API layer.
If you don't declare a type, the submitted value is stored as-is.Existing untyped data keeps working as before, so there's no need to retype everything in bulk.
| Rule | Details | What it means in practice |
|---|---|---|
| Max count | 20 / variant | If you need a 21st, rethink the design (a separate variant or a metafield) |
| Max length | 255 characters / barcode | Plenty for real-world identifiers; not meant for packing in concatenated values |
| Sort order | The first value you send is sorted to the front of the connection | You can design around putting the "primary identifier" first |
| Write behavior | Full replacement barcodes A write replaces the entire set |
always include the barcodes you want to keep. It is not a partial patch |
| Mutual exclusion | Not allowed In a single variant input, barcode and barcodes cannot both be set |
Migration-era code that sets both will fail. Commit to one or the other |
| Search filter | products / productVariants 's barcode filter matches any single entry |
searching by a secondary identifier still returns a hit |
barcodes: [新しい値] intending to add just one, every existing barcode is wiped. Always implement it as read → merge → send the full set , in that order.ProductVariant.barcode is now deprecated, butnothing breaks as of today. It is enough to remember the behavior as "it always points to the first item in the connection."
barcode , you getthe first entry in the barcodes connectionback.
barcode updates only the first entry, andleaves the other barcodes untouched.
Sending an empty value clears the first entry, andthe next barcode in the set moves up. The same behavior repeats until none are left.
barcode see just "one of them," andget no signal that the others even exist.barcodes connection.
Catch every barcode read in your code. Prioritize the paths that write out to external systems.
connection to fetch every entry, filtering by type when needed. Where a single barcode is enough, take the first one explicitly.
barcodes is a full replacement, so switch to "read → merge → send everything."barcode cannot be used alongside it, so standardize on one.
barcodes replaces the variant's entire set.send everything you want to keepis mandatory. Reusing an existing app's update code as-is will wipe them all out.
You cannot set both in a single variant input. A "write both to be safe" implementation is not viable mid-migration, so decide which one each path uses and commit to it.
Declaring UPC / EAN / ISBN / GTIN / ASIN validates character set, length, prefix, and check digit.The moment you declare a type, dirty data that used to pass through starts getting rejected— keep that in mind.
Legacy screens and not-yet-migrated integrations always read the first entry.What you put first is itself your compatibility design. Pinning the primary identifier to the first slot in line with your migration order prevents incidents.
Silent truncation raises no exception and no warning.Apps that sync identifiers to ERP / marketplace / POS / supplier feedscan end up quietly pushing wrong data even if nothing breaks tomorrow. There is no deprecation date yet (a future announcement plus one API version of notice), butmigration urgency is driven by data integrity, not by the deprecation date.
productVariantsBulkUpdate barcodes input. Where the standard is known, declare type so the values pass validation.barcode filter. The inventory process also surfaces invalid values.barcode and sync that to external systems. The moment a merchant registers a second barcode, incomplete identifiers keep flowing outward (with no warning).barcode reference in your integration code and replace it withbarcodes connection reads. As an interim step before migrating, extract the variants that have two or more barcodes and report on them.productVariants and check the count of barcodes . There is no deprecation date yet, butthe impact starts well before the deprecationis the point to watch.type(UPC / EAN / ISBN / GTIN / ASIN) when writing so the value passes Shopify's validation. For values whose standard can't be determined, send them with no type declared and they are stored as-is.barcode is deprecated but won't break today. However, from the moment a second barcode is registered,barcode -only integrations will silently drop identifiers.barcodes rather than waiting for the sunset date."