← Blog

Magento

Magento 2 to Shopware 6: the importer's 17 silent traps

An Antwerp B2B catalogue, 6,200 SKUs, moved from Magento 2 to Shopware 6 over one weekend. The importer logged zero errors. Tuesday lunchtime, the B2B prices were wrong.

Jacob Molkenboer· Founder · A Brand New Company· 6 Jun 2026· 9 min
Open leather ledger with handwritten price columns, green silk ribbon, brass key on index card, red shipping tag on ivory paper.

The migration was supposed to be the calm part. We had four developers, a frozen Magento 2.4.6 staging copy of an Antwerp wholesaler's catalogue (6,200 SKUs, fourteen customer groups, three languages), and a Shopware 6.6 target with the official Migration Assistant primed. The importer ran on Saturday night. By Sunday morning the dashboard said 6,217 products imported. Zero red rows, zero warnings. We told the client it was done and went off shift.

By Tuesday lunchtime, the B2B account manager was on a call. Every Reseller-tier price was showing the public list price. The Pro customer group, supposed to see net amounts, was being shown VAT-inclusive numbers. The bestseller, a 25-litre industrial sealant in three pack sizes, had three orphan variants in the catalogue and no parent product.

The Migration Assistant had not lied. It had done what every importer between two non-trivial e-commerce platforms does: mapped what it knew, defaulted what it didn't, and stayed quiet about the rest. This is the cheatsheet we wish we had walked in with.

Why silent is the dangerous category

Shopware's Migration Assistant is honest about hard failures. Invalid UTF-8, missing required fields, broken foreign keys: those throw, log, and halt the worker. The traps below are different. Every one of them produces a successful import. The data lands in the database. It is just wrong in a way that surfaces three to fourteen days later, usually through a customer email or a finance reconciliation.

We ranked by silence, not by frequency. Number one is the trap with the highest chance of producing a green tick and a Monday-morning incident. Number seventeen you will catch in your first smoke test.

Warning

The Migration Assistant's success counter measures rows written, not semantics preserved. Treat it as a transport receipt, not a QA report.

The seventeen traps, ranked by silence

  1. Customer-group tier prices. Magento stores tier prices per (product, customer_group_id, qty) in catalog_product_entity_tier_price. Shopware 6 has no native group-tier pricing on the product entity. The assistant writes them into the B2B Suite Advanced Prices module if you have the licence, and silently drops them if you do not. The product page still shows a price. It is the list price.
  2. Net versus gross customer groups. Magento decides net-vs-gross display via store config plus customer-group tax class. Shopware 6 has a single boolean on the group itself (displayGross). The assistant defaults every imported group to true. A reseller group that was net in Magento now shows VAT-inclusive prices in Shopware. Database values are correct, on-screen prices are wrong by 21%.
  3. Multi-source inventory collapsed to one number. On Magento 2.3+ with MSI, each SKU has rows in inventory_source_item per warehouse. Shopware 6 stores stock as a single integer on the product, with warehousing pushed to plugins. The assistant sums sources. A SKU with 12 in Antwerp and 0 in Rotterdam imports as 12 available, which is true today and false the moment the Antwerp box ships.
  4. Special prices with date ranges. Magento honours special_price_from and special_price_to on the storefront. The assistant writes the special into Shopware's listPrice and price fields, then drops the date range. Your Black Friday discount becomes the permanent June price.
  5. Tax classes matched by name, not by rate. If your Magento tax classes are labelled "Taxable Goods" and the Shopware target has "Standard rate", the assistant matches by string. Anything unmatched defaults to the standard rate UUID. Cart totals look right because most products land on the same rate. Per-product breakdowns are wrong for reduced-rate items.
  6. Configurable parents linked to the wrong simples. The assistant maps Magento configurable products to Shopware main products, and child simples to variants. If the configurable axis attribute (size, colour) did not migrate as a configurator-relevant property in step one, the variant linkage attaches by SKU pattern guess. Orphan simples appear in the catalogue with no parent.
  7. Bundle products vanish or fragment. Magento bundle product type has no native Shopware 6 equivalent. The assistant either skips bundles (a row in the error log only if you opted in to verbose) or imports the components as standalone simples. Your bundle SKU stops existing. The simples are findable by search; the bundle's landing page returns 404.
  8. Downloadable products lose their files. Magento's downloadable_link and downloadable_link_purchased tables do not have a Shopware analogue. The assistant imports the product as a standard item with no digital flag, no file, and no download history for past customers.
  9. URL rewrites and historic 301s. Magento's url_rewrite table holds years of category renames, product slug changes, and manual 301s. The assistant migrates current canonical slugs and ignores the rewrite history. Every legacy URL returns 404 unless you write your own importer into seo_url (see the Shopware SEO docs).
  10. Manufacturer attribute exploded into duplicates. Magento's manufacturer is an EAV dropdown with option labels. Shopware has a first-class manufacturer entity with name and slug. The assistant creates one manufacturer per unique label. Spelling variants in the source data ("3M", "3M Industrial", "3M ") become three separate brands with three brand pages.
  11. EAN custom attribute not mapped to the native EAN column. Most Magento catalogues store EAN/GTIN as a custom text attribute called ean or barcode. Shopware 6 has a native ean field on the product. The assistant maps custom-to-custom, leaving the native column NULL. Your Google Shopping feed ships with no GTINs and Merchant Center flags the entire feed.
  12. Layered nav properties imported as not filterable. Magento attributes carry is_filterable=1. Shopware property groups have a filterable boolean. The assistant copies the property and leaves filterable=false. Category pages render, the filter sidebar is empty, conversion drops.
  13. Cross-sells and up-sells flatten to empty streams. Magento's catalog_product_link stores related, cross-sell, and up-sell pairs. Shopware 6 represents these as cross-selling entities with a product stream or a manual list. The assistant creates the entities and forgets to attach products. The product page renders the cross-selling block; the block is empty.
  14. Decimal attributes with comma separators. Continental Magento catalogues often store decimals as "12,5" in varchar EAV cells. Shopware decimal fields expect a dot. The assistant casts what it can and silently writes 0 for what it cannot. Weights, dimensions, and litre values land as zero on roughly 1% of rows.
  15. Custom options on simples. Magento's catalog_product_option covers per-product extras: engraving text, gift wrap, length cut. Shopware 6 has custom field sets and product features, neither of which is a direct match. The assistant drops the entire catalog_product_option structure. The order form loses the input.
  16. Product visibility downgraded. Magento has four visibility values: not visible, catalog only, search only, catalog and search. Shopware 6 has a single active boolean plus category assignment. The assistant lands every visible product as active. Search-only products that were intentionally hidden from category pages now appear everywhere.
  17. Weight unit assumed kg. Magento stores weight in whatever unit the store config declares (usually kg, sometimes g for small parts). Shopware 6 stores weight in kg, full stop. A catalogue configured for grams imports as if every number were kilograms. A 250 g sachet becomes a 250 kg pallet and shipping rate calculation breaks for the whole category.

The pre-flight diff that would have saved us four days

The pattern across all seventeen is the same: the source schema has structure the target does not natively model. The fix is not a smarter importer. It is a five-query audit run against your Magento database before the migration kicks off, then re-run against Shopware after.

-- Run on Magento 2 source, then compare each count on the Shopware target.
SELECT 'tier_prices' AS k, COUNT(*) AS n FROM catalog_product_entity_tier_price
UNION ALL SELECT 'special_prices', COUNT(*) FROM catalog_product_entity_decimal
  WHERE attribute_id = (SELECT attribute_id FROM eav_attribute
    WHERE attribute_code = 'special_price' AND entity_type_id = 4)
UNION ALL SELECT 'configurables', COUNT(*) FROM catalog_product_entity WHERE type_id = 'configurable'
UNION ALL SELECT 'bundles', COUNT(*) FROM catalog_product_entity WHERE type_id = 'bundle'
UNION ALL SELECT 'downloadables', COUNT(*) FROM catalog_product_entity WHERE type_id = 'downloadable'
UNION ALL SELECT 'msi_stock_rows', COUNT(*) FROM inventory_source_item
UNION ALL SELECT 'url_rewrites', COUNT(*) FROM url_rewrite WHERE entity_type IN ('product','category')
UNION ALL SELECT 'custom_options', COUNT(*) FROM catalog_product_option
UNION ALL SELECT 'cross_sells', COUNT(*) FROM catalog_product_link WHERE link_type_id = 5;

Run the equivalent against Shopware 6 after the import (product_price for advanced prices, seo_url for rewrites, product_cross_selling joined to product_cross_selling_assigned_products for actual attached cross-sells) and compare line by line. If any number is smaller on the target, you have a silent trap. The query takes thirty seconds to run and produces the contract your importer has to honour.

One footnote on choice of stack

Shopware 6 is a credible Magento target in the EU specifically because it is European: Berlin-headquartered, GDPR-native, with a pricing model that does not require an Adobe Commerce contract. The repositioning of Magento under Adobe has pushed mid-market merchants in the €1M to €50M GMV band to look hard at alternatives, and Shopware has been the most obvious landing spot. Wholesalers in Antwerp, Eindhoven, and Düsseldorf are following the same logic for the same reason, and the catalogue trap list above is the toll they pay on the way through.

The smallest thing you can do today

If you have a Magento 2 to Shopware 6 move on your roadmap, run the audit query above against your source database this afternoon and paste the nine numbers into a shared sheet. When we handled the migration onto Shopware 6 for the Antwerp wholesaler, the trap that bit us hardest was the customer-group net-vs-gross flag. The fix took twenty minutes once we knew which products were affected; finding which products were affected, without that pre-flight diff, took four days.

Key takeaway

The Shopware Migration Assistant's success counter measures rows written, not meanings preserved. Diff the database before you trust the green tick.

FAQ

Does the Shopware Migration Assistant warn you about silent drops?

No. The Assistant logs only hard failures such as broken foreign keys, missing required fields, or encoding errors. Anything that maps to a default value or to a missing target field imports as success.

Do you need the Shopware B2B Suite to keep customer-group pricing?

For product-level tier pricing per group, yes. Without B2B Suite, the closest native option is Rule Builder, which prices by condition not by group. Budget the B2B Suite licence into the migration cost.

What is the safest order to test post-import?

Run the pre-flight count diff first. Then spot-check ten SKUs end to end: price by customer group, stock per warehouse, variant linkage, manufacturer slug, EAN field, and old URL 301s. If those pass, broaden the sample.

Can the Migration Assistant handle Magento 1 catalogues?

Not directly. Magento 1 needs an intermediate step: export to CSV via a connector, or move to Magento 2 first and then run the Shopware assistant. The catalogue traps still apply at the second hop.

How long does a 6,000-SKU migration like this take in practice?

The technical import runs in hours. The semantic audit, mapping fixes, B2B price re-import, URL redirect map, and customer-group reconciliation took our team roughly three weeks of focused work.

magentomigratione-commercelegacy sitesarchitecture

Building something?

Start a project