Your page shows Home → AI Tools → ChatGPT issues. The Rich Results Test says the BreadcrumbList is valid. But Search Console’s Breadcrumbs report shows warnings or errors, or the trail in the SERP looks wrong or missing. Before you rewrite anything, split the problem into two very different cases, because the fix is opposite for each:
- The SERP trail looks wrong/short, but Search Console is clean. Most likely nothing is broken on your side. Since January 2025 Google no longer renders breadcrumbs on mobile search results (you see only the domain); they still render on desktop. See the mobile case below.
- Search Console’s Breadcrumbs report shows Error or Warning items. That is a markup problem on your side and it does affect eligibility. Jump to fixing the markup.
The classic underlying cause is that your JSON-LD is generated independently from the visible UI: different data sources, different label conventions, different locale handling. Google’s actual rule (from the structured data policies) is not “byte-identical to the UI” — it is don’t mark up content that is not visible to readers, and don’t mislead. So the goal is alignment, not pixel-matching: the names and links in your BreadcrumbList must reflect a real, on-page path.
Which bucket are you in
| Symptom | Likely cause | Where to go |
|---|---|---|
| SERP trail gone on phone, fine on desktop | Jan 2025 mobile change, not your markup | Mobile case |
Search Console: Either "name" or "item.name" should be specified | Missing name on a list item | Named errors |
Search Console: Missing field "item" (in "itemListElement") | Non-leaf item has no item URL | Named errors |
Search Console: Missing field "id" (in "itemListElement.item") | Two items share the same URL | Named errors |
UI says “AI Tools”, JSON-LD says ai-tools | Slug used where display name belongs | Cause 1 |
| Localized page shows English labels in schema | JSON-LD not translated | Cause 4 |
| JSON-LD has more levels than the page | Phantom “SEO” levels | Cause 5 |
The SERP breadcrumb is missing or short but Search Console is clean
This is the most common false alarm as of June 2026. In January 2025 Google announced it would stop showing breadcrumbs in mobile search snippets in all languages and regions, displaying only the domain. Desktop snippets are unchanged and still show the full trail. The change is now baked into the official breadcrumb docs, whose feature-availability line reads “available on desktop in all regions and languages where Google Search is available” — mobile is not listed.
So if you check on your phone and see only aitoolsguidebook.com where you used to see aitoolsguidebook.com › AI Tools › ChatGPT issues, that is expected behavior, not a markup bug. There is nothing to fix and no action required — Google still reads and uses the markup, and the desktop SERP and the Breadcrumbs report are unaffected. Confirm by viewing the same query on desktop.
Search Console’s Breadcrumbs report can also lag by a few days. If your source markup is correct, trust the source first and let the report catch up.
Named Search Console errors and what they mean
These are the messages that actually make a page ineligible for the breadcrumb rich result. Each maps to a concrete fix.
Either "name" or "item.name" should be specified (in "itemListElement")— aListItemhas no readable name. Give every item anamestring (oritem.nameif you use the nested object form).Missing field "item" (in "itemListElement")— a non-last item has no destination URL. Every item except the final leaf needs anitem(an absolute URL). The leaf may omititem; per Google’s docs, when it does, “Google uses the URL of the containing page.” If this error fires on what you think is the leaf, yourpositionnumbering is probably wrong, so Google thinks a middle item is the one missingitem.Missing field "id" (in "itemListElement.item")— usually fires when two list items resolve to the same URL, because Google treats the URL as the item id and now sees a duplicate. Make each non-leaf URL unique, or give the nesteditemobject a distinct@id.
Requirements you can check at a glance (per Google’s breadcrumb docs, June 2026): at least two ListItem entries; every item needs a name (the title shown to the user); position is an integer where position 1 signifies the beginning and each step increments by 1; item is the URL of the breadcrumb target (use absolute URLs); the trail represents a typical user path to the page (it should not fabricate a hierarchy that does not exist).
Common alignment causes
Ordered by hit rate, highest first.
1. JSON-LD uses slugs while the UI uses display names
{ "name": "ai-tools", "item": "https://site.com/category/ai-tools/" }
The visible UI shows “AI Tools” (capitalized, spaced); the JSON-LD name says ai-tools (the raw slug). This is a textbook “marked-up content not visible on the page” violation.
How to spot it: compare the visible label to the JSON-LD name, character for character. Capitalization and spacing both count.
2. URL casing or trailing-slash differences
JSON-LD: https://site.com/Category/AI-Tools. Visible anchor: https://site.com/category/ai-tools/. Same logical destination, different strings — and if the canonical version differs from the one in the trail, you can also create a soft duplicate.
How to spot it: compare each anchor href against the matching JSON-LD item. They should resolve to the same canonical URL (same casing, same trailing-slash policy).
3. UI omits the homepage; JSON-LD includes it (or vice versa)
UI shows “AI Tools → ChatGPT issues” (no Home); JSON-LD has Home at position 1. Or the reverse. A deliberate, consistent choice is fine, but an accidental difference between layers usually means the two generators disagree.
How to spot it: count visible breadcrumb items vs. itemListElement.length. If they differ for no intentional reason, you have drift between the two code paths.
4. Localized page ships English JSON-LD
A non-English page shows translated labels in the UI (“首页 → AI 工具”) but the JSON-LD still emits the English originals (“Home → AI Tools”). The schema then describes content that is not on the page.
How to spot it: open a non-default-language URL and compare JSON-LD name fields to the visible labels.
5. Phantom levels added for “SEO”
Someone inserted intermediate levels that exist only in the markup (Home → AI → Tools → AI Tools → ChatGPT) believing it boosts SEO. The page shows fewer levels. This is exactly the “mislead / not visible” case Google’s policy prohibits, and it can suppress the rich result.
How to spot it: count JSON-LD positions. If the count exceeds the visible trail (plus the leaf), you have phantom levels. Remove them.
One legitimate exception: Google explicitly allows multiple
BreadcrumbListobjects on a page (an array) when several real navigation paths lead to it. That is different from padding one trail with fake levels — each list must still describe a genuine path.
The fastest fix
The durable fix is to compute the breadcrumb once and render both the visible UI and the JSON-LD from that single array. Then they cannot drift.
Step 1: Diff the two layers for one page
# Visible breadcrumb anchor text and hrefs
curl -s "https://site.com/article/" | grep -oP '<nav[^>]*aria-label="breadcrumb[^>]*>[\s\S]+?</nav>'
# JSON-LD breadcrumb block
curl -s "https://site.com/article/" | grep -oP '"@type":\s*"BreadcrumbList[\s\S]+?</script>'
Compare them position by position. Where the name or the canonical URL differs, you have your bug.
Step 2: Generate both from one source
---
const breadcrumb = [
{ name: 'Home', url: '/' },
{ name: 'AI Tools', url: '/category/ai-tools/' },
{ name: article.title, url: Astro.url.pathname },
];
const jsonLd = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": breadcrumb.map((b, i) => ({
"@type": "ListItem",
"position": i + 1,
"name": b.name,
// Omit `item` on the leaf so the last position has no link, per Google's spec
...(i < breadcrumb.length - 1
? { "item": new URL(b.url, Astro.site).toString() }
: {}),
})),
};
---
<nav aria-label="breadcrumb">
<ol>
{breadcrumb.map((b, i) => (
<li>
{i < breadcrumb.length - 1
? <a href={b.url}>{b.name}</a>
: <span>{b.name}</span>}
</li>
))}
</ol>
</nav>
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)}></script>
One breadcrumb array drives both representations, so the name values are guaranteed identical and the leaf correctly drops its item.
Step 3: Localize at the source
const breadcrumb = [
{ name: t('breadcrumb.home'), url: lang === 'en' ? '/' : `/${lang}/` },
{ name: t(`category.${article.category}`), url: `/${lang}/category/${article.category}/` },
{ name: article.title, url: Astro.url.pathname },
];
Because both layers read the same breadcrumb array, translating the labels once fixes the UI and the JSON-LD together.
Step 4: Add a CI guard (subset check, not byte-equality)
A strict byte-equality assertion is too brittle now — it breaks the legitimate “simplified visible trail, fuller schema path” pattern and the multiple-BreadcrumbList case. Assert instead that every JSON-LD name actually appears in the visible breadcrumb, which catches slugs, untranslated labels, and phantom levels without false positives:
// scripts/check-breadcrumb.mjs
import fs from 'node:fs';
import { parse } from 'node-html-parser';
for (const file of getDistHtmlFiles()) {
const root = parse(fs.readFileSync(file, 'utf8'));
const visible = new Set(
root.querySelectorAll('nav[aria-label="breadcrumb"] a, nav[aria-label="breadcrumb"] span')
.map(el => el.text.trim())
);
for (const script of root.querySelectorAll('script[type="application/ld+json"]')) {
let data;
try { data = JSON.parse(script.text); } catch { continue; }
for (const node of [].concat(data)) {
if (node['@type'] !== 'BreadcrumbList') continue;
for (const item of node.itemListElement) {
const name = item.name ?? item.item?.name;
if (name && !visible.has(name)) {
console.error(`MISMATCH in ${file}: JSON-LD "${name}" not in visible breadcrumb`);
}
}
}
}
}
Step 5: Validate and resubmit
Open the fixed URL in the Rich Results Test — it shows only Google-eligible features, so it is the right tool for breadcrumb eligibility (use the Schema Markup Validator only for full schema.org spec checks). Then in Search Console run URL Inspection → Test live URL on a representative page and Request indexing. The Breadcrumbs report typically refreshes over 1–2 weeks; valid items move out of the Error/Warning state on the next recrawl.
How to confirm it’s fixed
- Rich Results Test reports the page eligible for Breadcrumbs with zero errors, and the previewed names match your visible trail.
- The
nameof everyListItemis also visible somewhere in the on-page breadcrumb. - URL Inspection’s rendered HTML shows the same
BreadcrumbListyou ship (rules out a CDN or edge transform stripping it). - After the next recrawl, the Search Console Breadcrumbs report shows the URL under Valid with no Error/Warning items.
Prevention
- Generate the visible breadcrumb and the JSON-LD from one helper.
- On bilingual sites, both layers must read the same translation source.
- Keep
itemURLs absolute and canonical (consistent casing and trailing-slash policy). - Don’t pad a single trail with phantom levels for SEO; if you need more than one real path, ship multiple
BreadcrumbListobjects instead. - When you change URL structure, regenerate both layers — never hand-patch the JSON-LD.
FAQ
- The breadcrumb vanished from my phone’s search result. Did I break something? No. Since January 2025 Google hides breadcrumbs on mobile snippets and shows only the domain. Desktop still shows the full trail, and the markup is still read. Nothing to fix.
- Can I omit the homepage from the breadcrumb? Yes, it’s allowed. Just be consistent across the UI and the JSON-LD; an accidental mismatch between layers is the actual problem.
- Should the last item link to the current page? Per Google’s spec the final leaf may omit
item; when it does, Google uses the URL of the containing page for that position. Including anitemon the leaf is also accepted. Either form works — just apply one convention site-wide. - The Breadcrumbs report shows no impressions or seems empty. Is it broken? Often not. Since the Jan 2025 mobile change, breadcrumbs only render on desktop, so impression-style metrics tied to the visible feature dropped. The report still tracks markup validity (Valid / Warning / Error), which is what you should watch; Google continues to read and use the markup.
- Rich Results Test passes but Search Console still warns — who’s right? Both can be. The test reflects current source; the report reflects the last crawl and can lag days. Fix the source, retest live, request indexing, and let the report catch up.
- My visible breadcrumb is simpler than my schema path. Is that a violation? Not necessarily. Google forbids marking up content that is not visible, but a shorter visible trail backed by a fuller, truthful schema path is allowed. Don’t invent levels that aren’t real navigation.
Related
- Structured data warnings
- FAQ schema invalid
- WebSite JSON-LD inconsistency
- Article date vs JSON-LD date mismatch
- Hreflang x-default Confusion in Bilingual Sites
- Twitter Card Image Not Showing When Sharing
- VideoObject Schema Not Recognized in Search Console
- HowTo Schema Deprecated But Template Still Emits It
- Product Schema Review Count Does Not Match Visible Reviews
- Article Schema Missing Required Field author.name
- Sitemap lastmod Is Always Today and Google Stopped Trusting It
Tags: #SEO #Troubleshooting #Debug #Structured data #Breadcrumb #JSON-LD