Why Address Validation Rejects Real Customers (And How to Fix It)

If your checkout rejects a customer in Dublin, Amsterdam or Toronto while working perfectly for everyone in Ohio, the postcode field is the first place to look. The bug is almost never in the customer’s typing. It is in a regular expression that was written against one country’s format and quietly applied to the world.

Last updated: 30 August 2026 · Tools SoShareIT editorial team

The five-digit assumption

A postcode field validated as ^\d{5}$ accepts the United States and rejects roughly two thirds of the countries that have postal codes at all. It is the single most common address bug in production, and it is invisible to the team that shipped it because everyone testing the form lives somewhere the rule happens to fit.

What makes it durable is that the failure looks like user error. The customer sees “please enter a valid postcode”, assumes they mistyped, tries again, gets the same message, and leaves. Nothing is logged as an error. Your funnel simply has a hole in it shaped like several countries.

Four patterns that break naive validation

These are the four structural differences that account for most rejections. Each one breaks a different assumption.

Post office pigeonhole boxes of different sizes illustrating varying postal code formats

Letters, not just digits

Canada writes K1A 0B1. The Netherlands writes 1012 JS. The United Kingdom writes anything from M1 1AE to EC1A 1BB. A digits-only rule rejects all three outright, and the customer has no way to comply because there is no digit-only version of their address.

Variable length within one country

This is the assumption that survives longest, because it is not obviously an assumption. UK postcodes are six, seven or eight characters depending on the outward code. Both M1 1AE and EC1A 1BB are correct and current. A rule that pins the length to seven rejects roughly the same customers every time and looks consistent while doing it.

Separators that are part of the format

Japan writes 100-0001, Poland writes 00-001, Brazil writes 01310-100, Portugal writes 1100-148. The hyphen is not decoration a user added — it is the format. Stripping it before validation, then storing the stripped version, produces a value the postal operator will not recognise later.

Countries with no postal code at all

Ireland had no postcode system until Eircode launched in 2015, and plenty of countries still have none. A required postcode field is not a validation problem so much as a design one: it asks for something that does not exist, and the only way through is to invent a value, which is worse than an empty field.

What to validate instead

The fix is not a longer regex. It is to stop treating the postcode as a standalone string and start treating it as conditional on the country field.

Branching railway point mechanism illustrating validation conditional on country

Swipe the table sideways to see every column.

Instead of Do this Because
One regex for every country A pattern per country, selected by the country field There is no international format to write one rule against
Making postcode required everywhere Required only where the country has one Forcing a value invites invented ones
Stripping spaces and hyphens Normalising case, keeping separators The separator is part of the code
Rejecting on pattern mismatch Warning, and letting the order through A lost sale costs more than a mis-keyed postcode
A fixed length A range, where the country allows one Several formats are genuinely variable

The last row is the one teams argue about, so it is worth stating plainly: for most businesses a warning is the correct behaviour. A hard rejection assumes your pattern is more likely to be right than the customer is about where they live, and that assumption is exactly what produced the bug.

How to prove your form is fixed

A fix you cannot demonstrate is a guess. The cheapest proof is a fixture set containing one format-valid postcode from each country you sell to, run through the form as part of your test suite.

That is what the generator on Tools SoShareIT is for — it emits codes built from each country’s real pattern, so a rejection in your suite is a genuine finding rather than an artefact of made-up test data. Pick the country, generate, paste. The reference tables on the same page list the pattern for each country next to the example, which is usually enough to write the per-country rule directly.

One caveat worth keeping in front of you while you work: a generated code is format-valid, not delivery-valid. It will exercise your regex correctly and it will not survive a carrier address check, which is the intended behaviour. If your test suite calls a real address-verification API, that step needs real addresses, and the terms of use explain why we draw the line there.

Frequently asked questions

What is the correct regex for an international postcode?

There isn’t one, and any answer offering a single expression is wrong. Postal codes are defined per country with no shared structure — some are digits only, some mix letters, several vary in length within the same country, and some countries have none. The correct implementation is a lookup keyed on the country field, not one clever pattern.

Should I reject or just warn on a postcode mismatch?

Warn, for almost every business. A hard rejection asserts that your pattern is more likely to be right than the customer is about their own address, and that assumption is what produced the bug. Let the order through, flag it for the fulfilment step, and you lose a mis-keyed postcode instead of a sale.

Why does my form reject valid UK postcodes?

Almost always a fixed length. UK postcodes run six to eight characters depending on the outward code, so M1 1AE and EC1A 1BB are both correct. A rule pinned to seven characters rejects a consistent slice of British customers and looks perfectly stable while doing it.

Is it safe to strip spaces and hyphens before validating?

No. In Japan, Poland, Brazil and Portugal the separator is part of the format, not user decoration. Strip it for comparison if you must, but store the value as entered — a stripped code is one the postal operator may not recognise later.

How do I test the fix without real customer addresses?

Build a fixture with one format-valid code per country you sell to. The generator on Tools SoShareIT produces them from each country’s real pattern, so a failure in your suite is a genuine finding rather than an artefact of invented test data.