Merchlint
Available now
Next, in this order
  • DeutschDE
  • EspañolES
  • FrançaisFR
  • ItalianoIT
  • PortuguêsPT
  • NederlandsNL
  • SvenskaSV
  • TürkçeTR

A language shows up here once its pages are actually written. Nothing on this site is machine-translated.

Install free
← All checks

Invisible characters in the product code or name

The code looks right and matches nothing. Inside sits a character you cannot see — a non-breaking space from a spreadsheet, or a zero-width paste.

Group
Product identifiers
Confidence
F — fact from the database
Version
Pro
Updated
Code
G4

The symptom

You type a product code into the admin search and nothing comes back — even though the product is there and you can see it in the list. Your supplier returns the file saying they do not recognise the code. A stock integration creates a second record instead of matching the existing one. On screen the code looks exactly as it should.

Because the problem is not in what you can see. The field holds an extra character the browser does not draw: a non-breaking space carried over from a spreadsheet, a zero-width character from copying off a web page, or a tab from an export.

What it costs

A product code has one job: to be the same string of characters in your shop, at your supplier and in every system in between. An invisible character breaks that quietly.

  • Matching stops working. An import keyed on the code fails to find the product and creates a new one. After a few such runs your catalogue holds duplicates you cannot find by searching.
  • The admin search returns nothing. You type the code you can see on screen and get an empty result — which looks like a broken shop rather than broken data.
  • Feeds and marketplaces reject the offer, or accept it with a code nobody can later match back to an order.

Separately, and this is the nastiest part: two products can share a code without sharing it byte for byte. ABC-1 and ABC-1 with a trailing non-breaking space are the same code to a human and two different codes to a database. Such a duplicate trips no uniqueness check anywhere — not in the shop, not in the warehouse system.

How to check it yourself

From WP-CLI, no plugin needed — we look for bytes, not characters:

wp db query "SELECT p.ID, pm.meta_value AS sku \
  FROM wp_postmeta pm JOIN wp_posts p ON p.ID = pm.post_id \
  WHERE pm.meta_key = '_sku' AND pm.meta_value <> '' \
  AND (HEX(pm.meta_value) LIKE '%C2A0%' \
       OR HEX(pm.meta_value) LIKE '%E2808B%' \
       OR HEX(pm.meta_value) LIKE '%EFBBBF%' \
       OR pm.meta_value <> TRIM(pm.meta_value))"

Replace wp_ with your table prefix. C2A0 is a non-breaking space, E2808B a zero-width space, EFBBBF a byte-order mark. The query looks for them in hexadecimal, because in the output they would be invisible anyway.

How to fix it

  1. Copy the code out of the field and paste it into an editor that shows special characters — or simply retype the code from scratch. For a short code that is the fastest route.
  2. Do not rely on a spreadsheet’s “trim spaces” function. TRIM, in most spreadsheets and in SQL, does not remove a non-breaking space or a zero-width character. It only removes an ordinary space.
  3. Fix the source, or it comes back with the next import. The usual culprits are a spreadsheet column formatted as aligned text, and codes copied from a supplier’s web page straight into a sheet.
  4. After fixing, check whether you have created a duplicate — if the invisible character was the only difference between two products, cleaning it makes the codes identical and the shop will refuse one of them.

When it is a false positive

  • A code that genuinely contains a space, such as ABC 123. An ordinary space in the middle is a legal character and this check does not report it — it reacts only to characters you cannot see.
  • A product name with a deliberate non-breaking space. Typographic plugins bind short words to what follows them with a non-breaking space. That is why, in the name, this check does not report a non-breaking space or a soft hyphen — only control, zero-width and BOM characters.
  • A code imposed by an external system that you are not allowed to change. It happens with supplier-mandated codes. Hide the finding then — the problem stays, but knowingly.

How Merchlint finds it

Merchlint reads the raw value of the product code, the GTIN and the name — exactly as it sits in the database, with no cleaning on the way — and compares it with the same value after normalisation. A difference means the field holds a character that does not belong to the code.

Reported are: ASCII control characters, zero-width characters (U+200B–U+200D, U+2060), the byte-order mark (U+FEFF), the soft hyphen (U+00AD) and non-breaking spaces (U+00A0, U+202F, U+2007) at the edges and inside the code. In the name the scope is narrower and deliberately cautious: control, zero-width and BOM characters only.

The finding’s evidence shows exactly where the character sits, written as ⟨U+00A0⟩ in the place it occurs. Without that notation “trailing space” and “trailing non-breaking space” would look identical on screen, and they are two different repairs.

The same definition of a clean code drives the comparisons behind the duplicate checks, so the check and the comparison cannot drift apart: if Merchlint treats two codes as the same, it means they are identical once the invisible characters are removed.

Confidence: F — a fact from the database. The byte is either there or it is not.

This check is part of the Pro add-on.

Run this check on your store

Disagrees with what you see in your store? Write to us — we read every message. contact@merchlint.com