Command Palette

Search for a command to run...

12 Common Hreflang Errors and How to Fix Them

12 Common Hreflang Errors and How to Fix Them

T
Toolz Team
|Aug 23, 2026|12 min read

Part of the SEO Tools collection

Hreflang has a property that makes it uniquely annoying to debug: every failure mode produces markup that looks correct. There is no console error, no red badge in the browser, no build failure. The tags render, the page validates as HTML, and the annotation does nothing. You find out weeks later, from a Search Console report or from someone in another country telling you they got the wrong page.

I have debugged enough of these now to have a list. This is that list, ordered roughly by how often I find each one, with the symptom you would observe and the fix. It sits under the complete hreflang guide alongside the pieces on x-default and hreflang versus canonical.

TL;DR: The most common hreflang errors are missing return tags, non-ISO codes like en-UK, relative URLs, a canonical that points across languages, a missing x-default, and mixing implementation methods for the same URLs. All of them are silent: the markup renders and does nothing. Search Console's International Targeting report catches return-tag and unknown-code errors at scale; the rest need a crawl or a look at the rendered HTML. The hreflang tag generator validates codes, URLs, duplicates, and the missing fallback before you deploy.

1. Missing return tags

Symptom: Search Console reports "no return tags". Language versions do not swap in for the right markets, and the whole set behaves as if hreflang were absent.

Cause: Page A declares page B as its alternate, but page B does not declare page A. Google requires both sides to confirm the relationship and discards annotations that are not reciprocated.

Fix: Put the complete, identical set of annotations on every page in the group, including a self-referential entry. Do not try to be clever about which page needs which entry. The English page lists English, French, German, and x-default; so does the French page; so does the German page. Same block everywhere.

This is by a wide margin the most common failure, and it is nearly always caused by hand-editing per page or by a template that renders "the other languages" rather than "all languages".

2. Using non-ISO region codes

Symptom: Search Console reports "unknown language code", or nothing at all while the annotation is quietly ignored.

Cause: en-UK leads the field. UK is not an ISO 3166-1 alpha-2 code; the United Kingdom is GB. Invented regional codes like en-EU and es-LATAM are the same class of error, as is en-uk with the wrong casing paired with an already-invalid region.

Fix: Language from ISO 639-1, region from ISO 3166-1 alpha-2, joined by a hyphen. For Latin America, the valid answer is the UN M49 code es-419. For Chinese, prefer script subtags: zh-Hant and zh-Hans.

Wrong Right Why
en-UK en-GB UK is not an ISO 3166-1 code
en-EU Separate entries per country, or plain en The EU is not a country code
es-LATAM es-419 UN M49 region code for Latin America
zh-CH zh-Hans or zh-CN CH is Switzerland
CA en-CA and fr-CA Region alone is not valid

3. Region-only annotations

Symptom: Nothing happens. The annotation is ignored entirely.

Cause: Trying to target a country without naming a language, as in hreflang="US" or hreflang="CA". Hreflang is language-first by design; the region is an optional narrowing of a language, not a target on its own.

Fix: Name the language. If you serve Canada in two languages, that is two entries: en-CA and fr-CA.

4. Relative URLs

Symptom: The annotation is ignored. Frequently accompanied by "this works on my machine" because relative URLs resolve fine in a browser.

Cause: href="/fr/pricing" instead of href="https://example.com/fr/pricing". Hreflang requires fully qualified absolute URLs including protocol and host.

Fix: Emit absolute URLs. If you are building them in a template, build them from a configured site origin rather than a hardcoded string, so a staging deploy does not publish production URLs or vice versa.

5. A canonical that points across languages

Symptom: An entire language version disappears from the index. Hreflang appears correct and has no effect.

Cause: The French page declares the English page as its canonical. That instructs Google to drop the French URL, and a URL that has been canonicalized away cannot be served to anyone regardless of what hreflang says. Canonical is the stronger signal and it wins.

Fix: Every page canonicalizes to itself. Hreflang describes the relationships between those self-canonical pages. This one is worth its own read: hreflang vs canonical works through the combinations including parameterized URLs.

6. No x-default

Symptom: Visitors from countries you do not target land on an apparently random language version.

Cause: No fallback declared, so Google picks. Its pick is based on similarity signals that are not visible to you, which is how Dutch visitors end up on a German page.

Fix: Add one x-default entry per set, pointing at a language selector or your primary international version. The x-default guide covers where to point it and the mistakes that make it useless.

7. Mixing implementation methods

Symptom: Intermittent, hard-to-reproduce behaviour. Some pages swap correctly and others do not.

Cause: HTML <link> tags and XML sitemap xhtml:link entries both declaring hreflang for the same URLs. Each is valid alone. Together they are two sources of truth that drift, and when they disagree you have no way to know which one Google used.

Fix: Pick one method per URL set. HTML tags for most sites, sitemap entries when you have many locales and want lean page heads, HTTP headers for non-HTML files like PDFs. Then remove the other one rather than leaving it as a backup.

8. Trailing-slash and protocol mismatches

Symptom: Return tags fail even though both pages carry annotations.

Cause: The annotation points at https://example.com/fr while the indexable URL is https://example.com/fr/. Or it points at http:// on an HTTPS site. These are different URLs, so the return tag on the real page does not match the URL the other page named.

Fix: Use the exact canonical form of each URL, the same string you would put in a sitemap. Generate hreflang from the same URL builder your canonical tags use, so the two cannot disagree.

9. Pointing at redirects or 404s

Symptom: Partial or degraded behaviour; Search Console errors on the affected pairs.

Cause: A locale was retired and its URLs now redirect, or a translated page was deleted while the annotations that named it stayed. A redirect target still resolves, so it is not fatal, but it adds a hop and the return tag on the final URL may not match the URL that was named. A 404 target poisons the pair outright.

Fix: Crawl your own hreflang targets and check status codes. This is the check nobody runs, and it is the one that finds rot in sets that were correct when they were written.

10. Annotating noindex pages

Symptom: The set behaves inconsistently; some alternates never appear.

Cause: A page is advertised as a language alternate while carrying noindex. You have told Google both to serve this URL to a market and to keep it out of the index. The contradiction resolves in favour of noindex.

Fix: Either drop the annotation or drop the noindex. Staging leftovers and untranslated placeholder pages are the usual culprits.

11. Blocking hreflang targets in robots.txt

Symptom: Alternates never get confirmed. Search Console shows return-tag errors for pages that visibly carry return tags.

Cause: The target is disallowed in robots.txt, so Googlebot cannot fetch it and cannot see the return tag. The annotation on your side is fine; the confirmation on the other side is unreachable.

Fix: Allow crawling of every URL you name in an hreflang annotation. If a section genuinely should not be crawled, it should not be in a hreflang set either. The robots.txt generator is useful for auditing what your current rules block, which is often broader than intended.

12. Duplicate codes within one set

Symptom: Unpredictable. Google may take the first, the last, or discard the pair.

Cause: Two entries with the same hreflang value pointing at different URLs, usually because two systems both emit annotations, or because a locale map has a duplicate key. Two x-default entries are the same problem in its most common form.

Fix: One entry per code per set. View the rendered source rather than the template; a plugin adding a second block is invisible from the template alone. The free hreflang generator flags duplicate codes in the set you build, though it cannot see what else the page emits.

How do you find these errors systematically?

Three passes, in this order, because each one catches a different class.

Search Console first. The International Targeting report covers the whole property and finds the two errors that scale: missing return tags and unknown language codes. It lags behind your deploys by however long a full recrawl takes, so treat a week of no change as normal.

A crawl second. Any crawler that extracts hreflang gives you the set per URL. Group by cluster and compare counts: a page with four entries in a group of five is the bug. Then check the status code of every target, which is the pass that finds errors 8, 9, 10, and 11.

Rendered HTML last, for the specific page that is misbehaving. curl it, count the annotation blocks, count the x-default entries, and compare the URLs character by character against the canonical. This is where duplicates and trailing-slash mismatches show up, and it is the only pass that sees what a plugin injected at runtime.

The generator is worth running before any of that, because validating the set at the point you write it removes errors 2, 3, 4, 6, and 12 before they can ship. What no tool can enforce is reciprocity, since that is a property of pages other than the one in front of you. For that, the discipline is structural: one locale map, one renderer, the full block on every page. The Next.js and WordPress guides show what that looks like in code.

Frequently asked questions

What is the most common hreflang error?

Missing return tags. Page A names page B as an alternate but page B does not name page A, so Google discards the relationship. The fix is to put the complete identical set of annotations, including a self-referential entry, on every page in the group.

Why does Search Console say my hreflang has no return tags?

Because the page you pointed at does not point back with a matching annotation, or it points back at a slightly different URL. Trailing slashes, protocol differences, and www versus non-www all count as different URLs.

Is en-UK a valid hreflang code?

No. UK is not an ISO 3166-1 alpha-2 code. The correct code for the United Kingdom is GB, so the value is en-GB. en-UK is ignored silently.

Can hreflang URLs be relative?

No. Hreflang requires fully qualified absolute URLs including the protocol and host. Relative URLs are ignored even though they resolve normally in a browser.

Does a canonical tag override hreflang?

Effectively yes. If a page canonicalizes to a different language version, that URL is dropped from the index and hreflang cannot bring it back. Each page must canonicalize to itself.

How long do hreflang fixes take to show up?

Days to weeks. Google has to recrawl every page in the set before it can confirm the return tags, and Search Console reports update on the same schedule.

Can I use both HTML tags and sitemap hreflang?

You can, but do not. Two sources for the same URLs drift apart, and when they disagree there is no way to tell which one was used. Pick one method per URL set.

Do hreflang targets need to be crawlable?

Yes. If a target is blocked in robots.txt or marked noindex, Google cannot confirm the return tag and the annotation fails even though your markup is correct.


Comments

0 comments

0/2000 characters

No comments yet. Be the first to share your thoughts!