Key takeaways
- Almost every import failure is encoding, memory, SKU matching or a malformed row.
- An import that stops at the same row every time has a data problem, not a server problem.
- An import that stops at a different row every time has a server problem, not a data problem.
- That single distinction narrows the diagnosis faster than anything else.
WooCommerce imports fail in a small number of well-defined ways. The error messages are unhelpful, which makes it feel random. It is not.
Start with the one question that splits the problem space in half: does it fail at the same row every time, or a different one? Same row means the data is bad. Different row means the server ran out of something.
1. The import stops partway with no error
Cause: PHP timeout or memory exhaustion. The AJAX request died and the browser has nothing to report.
Fix: Raise max_execution_time to 300 and memory_limit to 512M. If your host locks these, split the file into batches of 200 to 500 rows. Check the actual reason in wp-content/debug.log after enabling WP_DEBUG_LOG.
Images are usually the real culprit, because they are downloaded inside the import request. A file that fails with images will often succeed with the Images column removed, which is a quick way to confirm the diagnosis.
2. Accented characters become question marks or mojibake
Cause: The file is not UTF-8. Excel's default "CSV" export writes Windows-1252 on most Western locales.
Fix: Re-save as CSV UTF-8 in Excel, or download as CSV from Google Sheets, which is already UTF-8. If you have shell access:
iconv -f WINDOWS-1252 -t UTF-8 old.csv > new.csv
Adding a byte order mark helps WooCommerce detect the encoding rather than guess it. There is no fixing this after import short of re-importing with update-existing ticked.
3. It fails at the same row every time
Cause: That row is malformed. Nearly always an unescaped quote or a stray line break inside a field, which throws off the column count for that row.
Fix: Open the CSV in a plain text editor, not Excel, and go to that row. Look for:
- A straight quote inside a quoted field that is not doubled.
15" screenmust be written15"" screen. - A hard line break inside a description field.
- A different number of commas than the header row.
To find every row with the wrong column count at once:
awk -F',' 'NR==1{n=NF} NF!=n {print NR": "NF" fields"}' products.csv
That is naive about quoted commas, so treat it as a shortlist rather than a verdict.
4. Products imported but variations do not show
Cause: The attribute is not flagged as used for variations. This is the single most reported WooCommerce import problem.
Fix: On the parent row, the attribute's in variations flag must be 1, and its visible flag should be 1 too. Without the first, WooCommerce imports the attribute as a display-only specification. The variation rows import fine and attach to nothing, so the product renders with a spec table and no dropdowns.
Re-import with the flag set and update-existing ticked. Editing products by hand does not scale past about five. The full flag reference is in the WooCommerce CSV schema explained.
5. Duplicate products after a second import
Cause: WooCommerce could not match the incoming rows to existing products, so it created new ones.
Fix: Matching happens on ID first, then SKU. You need Update existing products ticked and a stable identifier in every row. Blank SKUs match nothing. SKUs that changed between exports match nothing.
To clean up, find duplicates by title:
SELECT post_title, COUNT(*) c
FROM wp_posts
WHERE post_type='product' AND post_status='publish'
GROUP BY post_title HAVING c > 1;
Back up before deleting anything, and check which copy carries the images and reviews.
6. Images did not import
Cause: Four possibilities, in order of likelihood.
- Timeout. Downloads exceeded the request budget. Smaller batches.
- Hotlink protection. The source blocks requests without a matching referer, so WooCommerce receives a 403.
- Relative URLs.
/wp-content/uploads/tee.jpgis skipped. Needs the fullhttps://form. - Source is already offline. Nothing to fetch.
Fix: Test a URL with curl -I from the destination server, not from your laptop. A 200 from your browser and a 403 from the server is the classic hotlink signature.
Do not decommission the source until images are confirmed. WooCommerce does not retry later. Once the source domain is gone, those images are unrecoverable except from a backup.
7. Prices all imported as zero
Cause: The price column contained something that is not a bare decimal, or it was mapped to the wrong field.
Fix: Strip currency symbols, thousands separators and spaces. Convert comma decimals to full stops: 1.299,00 from a European locale must become 1299.00. Also confirm on the mapping screen that your column went to Regular price and not Sale price, which is a surprisingly easy misclick.
8. Products import but do not appear on the shop page
Cause: Usually Published or Visibility in catalog.
Fix: Published takes 1 for published, 0 for private, and -1 for draft. Zero is the trap: private products are published but visible only to admins, so the store looks empty while wp-admin shows everything present. Also check Visibility in catalog is visible and not search or hidden.
9. Categories duplicated with slight variations
Cause: Inconsistent whitespace around the > separator, or trailing spaces.
Fix: Normalise before import. In a spreadsheet, TRIM() the column and standardise on Parent > Child with exactly one space either side. Merge the duplicates afterwards under Products, Categories.
10. "Invalid file type" on upload
Cause: WooCommerce checks MIME type, not just the extension. Files saved as .csv by some tools carry a MIME type WordPress rejects.
Fix: Open and re-save through a plain spreadsheet application or a text editor. If it persists, upload to wp-content/uploads/ via FTP and use the "or enter the path to an existing file on the server" option on the import screen, which skips the upload check entirely.
11. Import completes but the count is wrong
Cause: Rows were skipped silently. Blank SKU on a row where a SKU is expected, a missing Type, or a variation whose Parent does not resolve.
Fix: The importer shows a "skipped" count on the results screen that is easy to miss. Check it. Then confirm that every variation's Parent value exactly matches an existing parent SKU, including case, and that parents appear before their variations in the file.
12. The site is slow after a large import
Cause: WooCommerce's lookup tables and term counts are stale, and thumbnails may not exist.
Fix: Run these in order:
wp wc update
wp term recount product_cat product_tag
wp media regenerate --yes
Then in the admin, WooCommerce, Status, Tools, and run Regenerate product attributes lookup table. Skipping that one makes filtered navigation and attribute-based sorting return wrong results, which is a bug report you will otherwise receive from a customer.
Or stop debugging CSVs entirely
Our free WordPress plugin reads a live Scrapify feed and handles encoding, batching, retries and image fetching for you. No file to malform.
A pre-import checklist
Ten minutes here saves a day of the above:
- File saved as UTF-8.
- Every row has the same column count as the header.
- Every product has a unique, stable SKU.
- Prices are bare decimals with a full stop.
- Image URLs are absolute and return 200 from the destination server.
- Parents sorted before variations.
- Attribute in-variations flags set on every variable parent.
Publishedis 1 or -1, never 0 unless you mean private.- Tested on a 5 row file first.
- Full database backup taken.
That last one is not optional. Imports with update-existing ticked can overwrite good data with bad across the entire catalogue, and there is no undo.