Back to Blog
Guides18 min read21 August 2026

Common Schema Markup Errors and How to Fix Them (2026)

The structured-data errors and warnings that show up again and again in Google's Rich Results Test: what causes each one, and exactly how to fix it.

By AI Schema Gen Team

Common Schema Markup Errors and How to Fix Them

If you've run a page through Google's Rich Results Test and gotten back a wall of red errors or yellow warnings, you're not alone, the same handful of mistakes account for most of what shows up there. This guide walks through the errors and warnings you'll actually encounter, in the order you're likely to hit them, with the specific cause and fix for each. No theory, no padding, just the messages, what they mean, and how to make them go away.

One thing worth knowing up front, because it reframes everything that follows: errors and warnings are not the same severity, and treating them the same wastes your time. An error means a required property is missing or invalid, and it blocks that rich result from appearing at all. A warning means a recommended property is missing or a value could be stronger, and the item stays eligible without it. Fix every error. Triage warnings against whether the missing property would genuinely improve what a person sees in the result, a dateModified warning on a page you've never modified isn't a real gap; a missing image on an Article that would show a thumbnail is.

With that framing, here's every common cause, organized by how it actually shows up in the tool.

"Missing field [property] (required)"

What it means: The most common error you'll ever see. A property Google's rich-result spec marks as required (name, image, price, author, startDate, and so on, depending on the type) simply isn't in your JSON-LD.

Why it happens: Almost always one of two things. Either the markup was written from a generic template that doesn't reflect what the specific page actually needs (an Event template missing location because the person who built it didn't fill in every field), or a field that's populated in the CMS isn't mapped into the schema output at all, the data exists on the page, it just never made it into the structured data.

The fix: Check Google's structured-data documentation for the type in question (each type, Article, Product, Event, Recipe, and the rest, has its own required-vs-recommended list) and confirm every required property is present and non-empty. If the value exists on the page but not in your markup, that's a mapping problem in whatever generates your schema, not a content problem: fix the template or generator rather than adding it once by hand, or it'll be missing again the next time this content type is used.

"JSON-LD must be valid JSON" / "Unexpected token" / "Unparsable structured data"

What it means: The tool couldn't parse your JSON-LD as JSON at all. This is a syntax error, not a schema error, Google never even got to evaluating your properties, because the block itself doesn't parse.

Why it happens: A trailing comma after the last property in an object or array (valid in JavaScript in some contexts, invalid in strict JSON). A missing or extra closing brace or bracket. An unescaped double-quote inside a string value, a business name or description containing a " character that wasn't escaped to \". Or, in React/Next.js and similar frameworks, unescaped < characters when JSON-LD is injected into a <script> tag, which can break parsing and is also an XSS risk.

The fix: Run the raw JSON through a JSON validator (or your browser's dev console with JSON.parse()) before worrying about schema semantics at all, you can't debug property-level issues in a block that doesn't parse. For the React/Next.js escaping case specifically, < must be escaped before the JSON-LD is serialized into the script tag; we cover the exact pattern in our headless WordPress and Next.js schema guide. If you're hand-editing JSON-LD directly in a theme file, a trailing comma on the last line of an object is the single most common typo, check there first.

"The value of [property] does not match the expected type"

What it means: A type mismatch, you've supplied a string where schema.org expects a URL, an object where it expects a plain string, a number formatted as text where a number is expected, or vice versa.

Why it happens: Common specific cases: image supplied as a bare filename instead of a full, absolute, crawlable URL. price supplied with a currency symbol or thousands separator ("$45.00" or "1,200") instead of a plain number string ("45.00"). ratingValue or reviewCount supplied as a JSON number instead of the string format some implementations expect, or outside the valid range. sameAs supplied as a single string instead of an array, when multiple profiles exist.

The fix: Match the exact type schema.org specifies for that property, check the property's page on schema.org if you're unsure, since "expected string" and "expected URL" look similar in error messages but have different requirements. For price specifically: plain number, no symbols, no separators, currency handled separately via priceCurrency. For image: a full https:// URL your server actually serves, not a relative path.

"Either 'offers', 'review', or 'aggregateRating' should be specified"

What it means: Common on Product schema. Google wants at least one of these three signals to consider a Product page eligible for its full rich-result treatment, and none is present.

Why it happens: A Product block generated from basic fields (name, image, description) without pulling through pricing or review data that does exist on the page, or a product that genuinely has none of the three yet (no price shown, no reviews collected).

The fix: Add whichever of the three genuinely applies, most commonly offers with a price and availability. If the product truly has no price, review, or rating to show (a "contact for quote" item, say), this is a real limitation of the page's content, not a markup bug, there's no valid workaround that doesn't involve inventing data you don't have, which you should never do.

"The value of 'ratingValue' must be between 1 and 5" (or similar range warnings)

What it means: A numeric property has a value schema.org's or Google's spec considers out of bounds for that property, most often ratingValue outside a 1-5 scale (or whatever bestRating/worstRating you've declared), or a duration/percentage value that doesn't make sense for its property.

Why it happens: A rating system on a different scale (out of 10, or out of 100) mapped into ratingValue without also declaring bestRating, so Google assumes the default 1-5 scale and your "8" looks invalid.

The fix: If your scale isn't 1-5, explicitly declare bestRating and worstRating alongside ratingValue so the scale is unambiguous. If it genuinely is 1-5, check for a data-entry or calculation bug feeding the wrong number through.

"The value of 'price' does not match what is shown to users" / content-mismatch flags

What it means: This is the one category the Rich Results Test generally cannot catch structurally, it validates syntax and types, not whether your markup's numbers match what's genuinely visible on the page. Google's spam policies explicitly prohibit structured data that doesn't reflect the page's actual content, and violations here surface through Search Console's Manual Actions report or manual review, not as a Rich Results Test error.

Why it happens: Markup that's gone stale after a price change, a sale ending, inventory selling out, or a redesign that moved or removed the visible content the schema still describes. This is the single most common reason star ratings specifically vanish or get flagged, the classic case is an AggregateRating claiming 200 reviews when only 40 are visible on the page, usually left behind after a theme or plugin update. We go deep on the review-specific version of this in our guide to getting star ratings.

The fix: There's no validator that flags this for you, it requires actually opening the live page and comparing what a visitor sees against what your markup claims, for every field that could drift: price, rating, review count, availability, dates. This is exactly the failure mode that markup generated from your live content, rather than hand-maintained and forgotten, is built to prevent, because it's regenerated from the actual page rather than frozen at whatever the page looked like when someone wrote the JSON-LD.

"Missing image with minimum resolution" / image-quality warnings

What it means: An image property is present and valid as a URL, but the actual image Google fetched is too small or the wrong shape for the richest possible display.

Why it happens: Google's general guidance for structured-data images is to provide multiple high-resolution images across three aspect ratios (16:9, 4:3, 1:1); a single small thumbnail passed as your only image value will validate as present but trigger a quality warning, not an error. It's worth double-checking Google's current documentation for the type you're working with, since exact resolution guidance has shifted over time and can differ slightly by type (Article/Top Stories has historically had its own stricter guidance).

The fix: This is a warning, not an error, so your page stays eligible without fixing it. But if the rich result includes a visual (Article, Product, Recipe, Event), a stronger image measurably improves how the result looks, so it's worth prioritizing over most other warnings. Supply an array of image URLs at the recommended aspect ratios where you can, and make sure the dimensions declared (if you're using ImageObject with explicit width/height) actually match the real file, Google checks that the declared dimensions agree with the fetched image, and a mismatch reads as a quality signal against you.

Duplicate or conflicting entities on the same page

What it means: Not always a discrete error message, sometimes it shows as unexpected results, sometimes as Google picking one version of an entity over another, sometimes as outright validator confusion. The underlying problem: two schema sources on the same page each declaring their own version of the same entity (two separate Organization blocks, or two Article blocks) without being connected or coordinated.

Why it happens: Most often a plugin conflict: your SEO plugin's automatic schema plus a manually added JSON-LD block, or two plugins both outputting Organization schema, each unaware of the other. This is a real risk anytime you're layering a second schema source onto a site that already has one running (a theme, an SEO plugin, a page builder); even well-architected plugins that build a single connected @graph warn that a second, uncoordinated source can create exactly this conflict.

The fix: View source on the page and inventory every JSON-LD block actually present, not just the one you meant to add. Decide which source owns which entities, and disable the overlapping output from the other. If you're intentionally combining sources, connect them by @id rather than letting each declare its own independent copy of the same entity, a connected graph, not duplicate descriptions.

"The property [X] is not recognized" / unsupported or misspelled properties

What it means: A property name in your JSON-LD isn't one the validator recognizes for that type, usually shown as a soft warning rather than a hard error, since unrecognized properties are typically just ignored by Google rather than treated as invalid.

Why it happens: A typo in the property name (a non-ASCII character that looks identical to a Latin letter, or a missing letter like priceCurency), a property from a different schema.org type mistakenly used on this one, or a property that exists in the general schema.org vocabulary but isn't one Google's specific rich-result implementation reads.

The fix: Check the exact spelling and casing against schema.org's property list for that type, property names are case-sensitive and this is an easy typo to make by hand. If the property is valid schema.org vocabulary but not read by Google's rich results, that's not a bug to fix; it may still be useful for other consumers (AI crawlers, other search engines) even without a Google rich-result payoff, which is worth knowing before you strip it out.

eventStatus, eventAttendanceMode, and other enum values in the wrong format

What it means: Properties that take a fixed set of values from schema.org's enumeration (eventStatus, eventAttendanceMode, availability, itemCondition) rejected because the value isn't one of the accepted forms.

Why it happens: These properties require the full schema.org URL form (https://schema.org/EventScheduled, not "Scheduled" or "EventScheduled" alone), and it's an easy shorthand to reach for when hand-writing markup.

The fix: Always use the complete URL form for enumerated values, copied exactly from schema.org's documentation for that property rather than typed from memory. This category is a frequent source of silent failures because a shortened value often doesn't throw a hard error, it just doesn't register as the value you intended, and the property behaves as if it were empty.

Structured data present in the DOM but invisible to the validator

What it means: You can see the JSON-LD when you inspect the page in your browser's dev tools, but the Rich Results Test reports no structured data found at all.

Why it happens: Almost always a rendering issue. If your JSON-LD is injected client-side by JavaScript after the initial page load, a crawler that reads server-rendered HTML, which describes how structured-data crawling generally works, may load the page before that script runs and see nothing. This is a well-documented failure mode in headless and JavaScript-framework builds specifically, where a frontend that used to get schema "for free" from a server-rendering CMS now has to render it explicitly itself.

The fix: View source (not the browser's DOM inspector, which shows the post-JavaScript state) to confirm your JSON-LD is actually present in the raw HTML response. If it isn't, move the schema into your server-rendered or statically-generated output rather than a client-side effect. Our headless WordPress guide covers exactly this failure mode and the fix for Next.js and similar frontends in detail.

Structured data on a page blocked from crawling entirely

What it means: The Rich Results Test can't evaluate your markup at all, returning a crawl failure rather than a schema error.

Why it happens: The page is disallowed in robots.txt, carries a noindex directive, or sits behind a login wall or bot-blocking rule, none of which are schema problems, but all of which mean Google never gets far enough to read your JSON-LD regardless of how correct it is.

The fix: Confirm the page is genuinely crawlable and indexable before troubleshooting the markup itself, check robots.txt, meta robots tags, and any CDN or firewall-level bot rules (Cloudflare and similar services have blocked AI and search crawlers by default in some configurations). This is a five-minute check that saves a lot of wasted time debugging schema that was never the actual problem.

Common mistakes to avoid

Chasing every warning to zero. Warnings flag recommended properties, not requirements. A warning on a field that's genuinely irrelevant to your content isn't a gap to fix, it's the validator being generic about a type it can't fully judge for your specific page.

Assuming a passing Rich Results Test guarantees the rich result appears. Google states plainly that passing validation doesn't guarantee display, eligibility is necessary, not sufficient, and Google still decides display algorithmically.

Fixing the symptom instead of the source. Manually patching a missing field in one page's JSON-LD fixes that page and leaves the underlying template or generator broken for the next hundred pages of the same type.

Testing only the homepage. A template-level bug affects every page built from that template. Test one page per content type, not just your most important page.

Ignoring content-mismatch drift because the validator didn't flag it. The validator checks syntax and types, not whether your numbers match your visible content. That category of error requires actually comparing the page to the markup, on a schedule, not a one-time check.

Validating your schema properly

Use the right tool for the right question. Google's Rich Results Test (search.google.com/test/rich-results) checks eligibility for Google's specific supported rich-result types, it's the tool for "will this show a rich result." The Schema Markup Validator at validator.schema.org checks broader schema.org validity, including vocabulary Google doesn't use for search features at all, useful for types like Service that have real value for AI systems but no Google rich result to test for. Search Console's Rich Results Status report shows what Google's actually parsed across your whole site after crawling, which catches template-wide problems a single-page test won't reveal, and its Manual Actions report is where content-mismatch violations surface. View source, not the DOM inspector, whenever you need to confirm what's actually in the server-rendered HTML rather than what a script added afterward.

If you're validating as part of a build pipeline rather than checking pages one at a time after publishing, that's worth a dedicated look, see our guide to validating structured data in CI/CD for catching these errors before they ship rather than after.

Fixing the root cause: why the same errors keep coming back

Here's the pattern underneath almost every error above: hand-maintained schema drifts from the content it's supposed to describe, and templated schema misses whatever the template didn't anticipate. A price changes and the markup doesn't. A new content type launches and nobody adds its schema block. A redesign moves the visible reviews and the AggregateRating count stays frozen at the old number. None of these are one-time mistakes, they're the predictable result of maintaining structured data as a separate, parallel thing from the content it describes.

AI Schema Gen is built around the alternative: generating schema from your actual page content rather than a static template, so the properties present reflect what's genuinely on the page and stay in sync as that content changes, the price, the rating count, the availability, all pulled from the live page rather than frozen at whatever it looked like when someone wrote the JSON-LD by hand. It also validates before markup goes live, which catches the syntax and type-level errors covered above before they reach Search Console. That doesn't eliminate every category above (a page genuinely blocked by robots.txt is still blocked, and content-mismatch still requires the markup to be regenerated when the page changes rather than left static), but it removes the single biggest source of recurring errors: markup that was correct once and quietly stopped being correct as the page moved on without it.

Frequently Asked Questions


Tired of chasing the same schema errors after every content update? AI Schema Gen generates structured data from your live page content and validates it before it goes live, so the properties in your markup stay accurate as your pages change, instead of drifting into the errors above. Start free at aischemagen.com.

Generate perfect schema in 30 seconds

AI Schema Gen handles everything automatically, free to start.

Get Started Free