Structured Data with Syntax Errors Detected: How to Fix It
A syntax error in structured data means Google tried to read a block of markup on your page and could not parse it. Search Console lists these in the Unparsable structured data report, and the Rich Results Test flags them too. Unlike a warning about a missing field, a syntax error is all or nothing: Google ignores the entire broken block, so none of the information in it counts and the page loses any rich result that depended on it. The cause is almost always broken JSON-LD, such as a trailing comma or an unescaped quote mark. This guide shows you how to find the broken block, read the parser's message, fix the common mistakes, and fix the template so it cannot happen again.
What a structured data syntax error means
Structured data is extra information you add to a page so search engines and AI systems can read facts about it without guessing: that a page is a product with a price, an article with an author, or a business with an address. Most sites write it as JSON-LD, a block of JSON inside a <script type="application/ld+json"> tag.
JSON is strict. One misplaced character makes the whole block unreadable, and a parser that cannot read a block does not try to rescue the parts that look fine. That is why a syntax error is more serious than other structured data problems:
| Problem | What Google does | Where you see it |
|---|---|---|
| Syntax error | Ignores the whole block | Unparsable structured data report; Rich Results Test |
| Missing required property | Reads the block but the item is not eligible for that rich result | The rich result report for that type, as an error |
| Missing recommended property | Reads the block; the item stays eligible | The rich result report, as a warning |
The Unparsable structured data report groups errors by the parser's message. You will see wording such as Parsing error: Missing ',' or '}', Bad escape sequence in string or Missing ',' or ']' in array declaration. Each points at a specific kind of mistake, and the example URLs show you where to look.
The mistakes that cause it
| Mistake | Broken | Fixed |
|---|---|---|
| Trailing comma after the last item | "name": "Shears",} | "name": "Shears"} |
| Missing comma between items | "name": "Shears" "sku": "PS-1" | "name": "Shears", "sku": "PS-1" |
| Unescaped double quote in a value | "name": "12" Hinge" | "name": "12\" Hinge" |
| Curly quotes from a word processor | βnameβ: βShearsβ | "name": "Shears" |
| Single quotes | 'name': 'Shears' | "name": "Shears" |
| Comments | // product block | Remove them; JSON has no comments |
| Real line break inside a string | A description split over two lines | Write \n or remove the break |
| Lone backslash | "C:\docs" | "C:\\docs" |
| Unclosed brace or bracket | A block ending without } or ] | Close every object and array |
| Template code left in the output | "price": {{ price }} printed literally | Fix the template tag or the field it reads |
JavaScript allows trailing commas, single quotes and comments, so code copied from a script often looks right and still fails. JSON-LD must be pure JSON.
A less obvious cause is duplicate generators. A theme and an SEO plugin can both print schema, and if one of them prints a half-finished block, that block is the one in the report. Two copies of the same type also make results harder to read; see plugin schema conflicts.
How to find the broken block
Take an example URL from the report and run it through the Rich Results Test. It reports the syntax error and highlights the line in the code view. Then look at the page yourself, because pages often carry several blocks and you need to know which one is broken.
In Chrome, open DevTools, go to the Console and paste this. It tries to parse every JSON-LD block on the page and reports which ones fail:
document.querySelectorAll('script[type="application/ld+json"]').forEach((s, i) => {
try { JSON.parse(s.textContent); console.log(i, 'OK'); }
catch (e) { console.log(i, 'BROKEN:', e.message); console.log(s.textContent); }
});
The error message gives a position, such as Unexpected token } in JSON at position 214. Count to that character, or paste the block into a JSON validator, and the mistake is usually just before it.
From a terminal, you can pull the blocks out of the HTML the server sends and test each one:
curl -sS https://example.com/product/shears/ | python3 -c '
import sys, re, json
html = sys.stdin.read()
for i, b in enumerate(re.findall(r"<script[^>]*application/ld\+json[^>]*>(.*?)</script>", html, re.S)):
try: json.loads(b); print(i, "OK")
except json.JSONDecodeError as e: print(i, "BROKEN line", e.lineno, "col", e.colno, e.msg)
'
Compare the server HTML with what DevTools shows. If the block is fine in the server HTML but broken in the browser, a script is changing it after load. If it is broken in both, the problem is in the template or the content.
The schema debugger and the JSON checker do the same job and point at the line and character of the first error.
Fix the template, not just the page
When a CMS fills JSON-LD from page fields, the content itself can break the markup. A product called 12" Brass Hinge, a description with a line break, or a name with a backslash will produce invalid JSON if the template pastes the text straight in. The fix is to build the data as an object and let a JSON encoder write it, so escaping is done for you.
PHP and WordPress
<?php
$data = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $product_name,
'sku' => $sku,
'offers' => [
'@type' => 'Offer',
'price' => $price,
'priceCurrency' => 'GBP',
],
];
?>
<script type="application/ld+json">
<?php echo wp_json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG ); ?>
</script>
Outside WordPress, use json_encode with the same flags. JSON_HEX_TAG turns < and > into escape codes, so a value containing </script> cannot end the tag early.
Shopify Liquid
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": {{ product.title | json }},
"description": {{ product.description | strip_html | json }}
}
</script>
The json filter adds the surrounding quotes and escapes the content, so do not wrap it in quotes yourself.
Next.js and React
const data = { '@context': 'https://schema.org', '@type': 'Product', name: product.name };
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(data).replace(/</g, '\\u003c') }}
/>
Replacing < with its escape code does the same job as JSON_HEX_TAG. See JSON-LD in Next.js for where to place the block.
Platform notes
- WordPress. Most broken blocks come from custom code in the theme, a page builder's custom HTML widget, or two plugins printing schema. Pasting JSON-LD into the block editor's paragraph blocks can convert straight quotes to curly ones; use a Custom HTML block or a plugin field. See JSON-LD in WordPress.
- Shopify. Themes print product schema in a snippet. Apps can add their own, and an app removed without cleaning up can leave a half-written block. Search the theme code for
application/ld+json. See JSON-LD in Shopify. - Tag managers. JSON-LD injected through a tag manager is added by JavaScript after load. It can work, but Google must render the page to see it, and a variable that returns nothing can leave an empty value with a trailing comma.
- Static and hand-coded sites. Edit JSON-LD in a code editor that highlights JSON errors, never in a word processor or rich text editor.
A worked example
A hardware shop sees 140 product URLs in the Unparsable structured data report with Parsing error: Missing ',' or '}'. Running the console script on one of them shows block 1 broken. The relevant part reads:
"name": "12" Brass Hinge",
The inch mark ends the string after 12, and the parser then finds Brass where it expects a comma. Escaping it as "12\" Brass Hinge" fixes this page. Sorting the report shows every failing product has an inch mark or a quote in its name, so the template is the real problem. It was building the block with string joining; changing it to build an array and output it with wp_json_encode fixes all 140 at once. The Rich Results Test then reads a valid Product item, and the owner validates the fix in Search Console.
The fix, step by step
Step 1
Collect example URLs from the report
In Search Console, open the Unparsable structured data report and note each error message and its example URLs. Group the URLs by template, such as product, post or category. Errors in one template usually share one cause. Pick one example URL per group and per message, so you can fix the cause once and confirm it on every affected template rather than working through hundreds of pages one at a time.
Step 2
Find which block is broken
Run the example URL through the Rich Results Test and read the error and highlighted line. Then open the page in Chrome and run a short script in the DevTools console that calls JSON.parse on every application/ld+json block and logs which ones fail. Write down which block is broken, what type it describes and the character position of the error, so you know exactly where to look in the source.
Step 3
Fix commas, braces and comments
Open the broken block in a validator or code editor that highlights JSON errors. Remove trailing commas after the last item in any object or array, add missing commas between items, close every brace and bracket, and delete any comments. Use straight double quotes for every key and string. Fix the first error reported, then validate again, because one early mistake can make every later line look wrong.
Step 4
Fix quotes and escaping in values
Check text values for characters that break JSON. Escape double quotes inside a value as \", escape backslashes as \\, and replace real line breaks inside strings with \n or a space. Replace curly quotes pasted from a word processor with straight ones. Then search your content for other pages with the same characters, such as inch marks in product names, because they will all fail in the same way.
Step 5
Change the template to use a JSON encoder
Find the template or code that prints the block and stop it pasting field values into a JSON string. Build the data as an array or object and output it with wp_json_encode or json_encode in PHP, the json filter in Shopify Liquid, or JSON.stringify in JavaScript, escaping the < character as well. Test a page whose content contains quotes or line breaks to confirm the output now parses.
Step 6
Remove duplicate and leftover generators
View the page source and count the JSON-LD blocks and microdata items. If a theme, a plugin and an app each print the same type, switch off all but one in their settings. Remove leftover code from apps or plugins you have uninstalled. Exclude JSON-LD blocks from minification and script combining in optimisation plugins. Reload the page and confirm each type now appears once and every block parses.
Step 7
Retest in both validators
Run the fixed URLs through the Rich Results Test and the Schema Markup Validator. The Rich Results Test confirms Google can parse the block and shows any rich result it qualifies for; the Schema Markup Validator shows every type on the page, including ones with no rich result. Test one page from each affected template. Both tools should read every block without a syntax error before you move on.
Step 8
Validate the fix in Search Console
Open the Unparsable structured data report, select each error message you have fixed and choose Validate fix. Google recrawls the affected URLs over the following days or weeks and removes them from the report as they pass. If validation fails, open the URLs it lists, check them with the console script again and look for another template or content pattern that still produces broken output.
Edge cases worth knowing
- Microdata and RDFa errors. Unparsable structured data can also come from microdata or RDFa, such as an
itempropoutside anyitemscope. These are HTML structure problems rather than JSON ones; fix the nesting in the template. - Valid JSON, wrong values. A block can parse and still be wrong, for example a price written as
"Β£12.99"instead of"12.99". That shows as an invalid value rather than a syntax error; see schema errors. - HTML entities in JSON. Some CMSs turn
&into&inside script tags. It does not break the JSON, but the value then reads literally as &. - Minifiers and optimisation plugins. A plugin that combines or minifies inline scripts can damage JSON-LD. Exclude
application/ld+jsonblocks from inline script processing. - Do not delete everything. Removing all schema hides the error but throws away the valid parts that describe the page. Fix the broken block instead.
Keeping your structured data valid
Syntax errors come back when content changes or code changes, so check both.
- Never build JSON-LD by joining strings. Build an object or array and let a JSON encoder write it.
- Keep one generator per schema type: either the theme, a plugin or your own code, not several.
- After a theme, plugin or app update, test one page of each template in the Rich Results Test.
- Add a check to your build or deployment that parses every JSON-LD block on a few sample pages and fails if any are invalid.
- Check the Unparsable structured data report in Search Console monthly; new entries usually follow a change you can name.
Our schema drift monitor watches your pages for markup that changes or breaks between checks.
1. What does unparsable structured data mean?
Unparsable structured data means Google found a block of markup on your page that it could not read because the syntax is broken. It is usually JSON-LD with a missing comma, an extra comma, an unescaped quote or an unclosed brace. Google ignores the whole block, so none of its information counts and any rich result based on it is lost. The Unparsable structured data report in Search Console lists the error message and example URLs, which show you where to start.
2. Does one syntax error break all the structured data on a page?
No, a syntax error breaks only the block that contains it, not every block on the page. Each JSON-LD script tag is parsed separately, so a broken product block does not stop a valid breadcrumb block from being read. Within the broken block, though, nothing counts, even the parts that look correct. That is why it helps to keep separate types in separate blocks or a well-formed graph, and to find out exactly which block is failing before you change anything.
3. Why does my JSON-LD work in JavaScript but fail in Google?
JSON-LD must be strict JSON, and JavaScript accepts several things that JSON does not. Trailing commas, single quotes around strings, unquoted keys and comments are all valid in a JavaScript object but invalid in JSON. Code copied from a script or written by hand often contains one of these. Run the block through JSON.parse or a JSON validator rather than relying on how it looks, and generate it with JSON.stringify or a server-side encoder so the output is always valid.
4. How do I escape quotes in JSON-LD?
Escape a double quote inside a JSON string with a backslash before it, and escape a backslash itself with a second backslash. A line break inside a value must be written as backslash n rather than a real new line. Rather than escaping by hand, let your platform's JSON encoder do it: json_encode or wp_json_encode in PHP, the json filter in Shopify Liquid, or JSON.stringify in JavaScript. That way product names with inch marks or quotes never break the markup.
5. Can a WordPress plugin cause structured data syntax errors?
Yes, plugins are a common source of syntax errors, either directly or through conflicts. A plugin may build JSON-LD by joining strings, so content with quotes breaks it, or two plugins may each print schema and one may leave a block half-written. Optimisation plugins that minify or combine inline scripts can also damage JSON-LD. Check which plugin printed the broken block, update or reconfigure it, keep one schema generator per type and exclude JSON-LD from script optimisation.
6. Should I delete my schema to get rid of the errors?
No, deleting all your schema hides the error but loses the benefit of the markup. Valid structured data helps search engines and AI systems understand what your page is about, and some types make pages eligible for rich results. Fix the broken block instead, usually a small change to one template. If a block comes from a plugin you no longer want, remove that plugin's output, but keep or replace the markup that correctly describes your pages.
7. How long does it take for syntax errors to clear in Search Console?
Syntax errors clear as Google recrawls the fixed pages, which usually takes days to a few weeks. Choosing Validate fix in the Unparsable structured data report asks Google to check the affected URLs and tracks progress for you. Pages that are crawled often clear quickly, while rarely crawled pages can take longer. You can confirm individual pages straight away with the Rich Results Test or a live URL Inspection test, without waiting for the report to update.
The schema debugger parses every JSON-LD block on your page, points at the line and character of each syntax error, and shows which types read correctly.
Open Schema Debugger Fixes β