Skip to main content

One post tagged with "Theme Development"

View all tags

Fix WordPress FSE Pattern Block Validation Errors - 5 Common Causes

· 4 min read

Encountered frequent Block Pattern validation failures while developing a WordPress FSE theme for a client. This article summarizes 5 common causes and solutions.

TL;DR

Block validation failures are usually caused by one of: undefined color slugs, duplicate JSON keys, Style Variation palette override, HTML attribute mismatch with block comments, or global styles overriding theme.json. Check each one systematically.

Problem

Patterns show a red warning in the editor:

Block contains unexpected or invalid content

After attempting to recover the block, it may work temporarily, but the issue returns after refresh.


Cause 1: Undefined Color Slug

Root Cause

Pattern block attributes reference color slugs that don't exist in theme.json:

<!-- Error: neutral-text doesn't exist -->
<!-- wp:paragraph {"textColor":"neutral-text"} -->
<p class="has-neutral-text-color">...</p>

Solution

  1. Open theme.json and check all colors defined in settings.color.palette
  2. Replace invalid slugs in your Pattern with valid ones
# Batch replacement example
cd patterns/
sed -i 's/"neutral-text"/"neutral-500"/g' *.php
sed -i 's/has-neutral-text-color/has-neutral-500-color/g' *.php

Valid slugs reference: primary, secondary, accent, base, contrast, neutral-50 through neutral-900


Cause 2: Duplicate JSON Key

Root Cause

Block comment JSON has duplicate keys at the same level (common when copy-pasting):

// Error: two style keys
{"style":{"typography":{...}},"style":{"spacing":{...}}}

JSON specification doesn't allow duplicate keys; parser behavior is undefined.

Solution

Merge into a single key:

// Correct
{"style":{"typography":{...},"spacing":{...}}}

Debug command:

# Search for potentially duplicate keys
grep -n ',"style":{' patterns/*.php | head -20

Cause 3: Style Variation Palette Override

Root Cause

color.palette in styles/*.json completely overrides (doesn't merge) the parent theme palette.

When a Pattern references neutral-500, but the current Style Variation doesn't define it, validation fails.

Solution

Each Style Variation must include the complete neutral series:

// styles/ocean.json
{
"version": 3,
"settings": {
"color": {
"palette": [
{ "slug": "primary", "color": "#0d9488", "name": "Primary" },
{ "slug": "secondary", "color": "#0f766e", "name": "Secondary" },
{ "slug": "accent", "color": "#f59e0b", "name": "Accent" },
{ "slug": "base", "color": "#f8fafc", "name": "Base" },
{ "slug": "contrast", "color": "#0f172a", "name": "Contrast" },
{ "slug": "neutral-50", "color": "#fafafa", "name": "Neutral 50" },
{ "slug": "neutral-100", "color": "#f5f5f5", "name": "Neutral 100" },
{ "slug": "neutral-200", "color": "#e5e5e5", "name": "Neutral 200" },
{ "slug": "neutral-300", "color": "#d4d4d4", "name": "Neutral 300" },
{ "slug": "neutral-400", "color": "#a3a3a3", "name": "Neutral 400" },
{ "slug": "neutral-500", "color": "#737373", "name": "Neutral 500" },
{ "slug": "neutral-600", "color": "#525252", "name": "Neutral 600" },
{ "slug": "neutral-700", "color": "#404040", "name": "Neutral 700" },
{ "slug": "neutral-800", "color": "#262626", "name": "Neutral 800" },
{ "slug": "neutral-900", "color": "#171717", "name": "Neutral 900" }
]
}
}
}

Key point: Neutral series color values must match theme.json exactly; only change brand colors.


Cause 4: HTML Attribute Mismatch with Block Comments

Root Cause

This is the most subtle issue. WordPress save function has strict requirements for generated HTML.

Issue 4.1: Incorrect class Order

WordPress generates classes in a fixed order:

has-border-color has-{slug}-border-color has-{slug}-background-color has-background

Wrong order in hand-written HTML causes validation failure.

Issue 4.2: Background Color Attribute Mixing

Background color must use backgroundColor attribute, not style.color.background:

<!-- Error: mixing causes invalid CSS generation -->
<!-- wp:group {"style":{"color":{"background":"#f5f5f5"}}} -->

<!-- Correct -->
<!-- wp:group {"backgroundColor":"neutral-100"} -->

Issue 4.3: Border Style Attribute Order

border-width must come before border-style:

<!-- Correct -->
<div style="border-width:1px;border-style:solid;border-radius:8px;">

Solution

Best practice: Copy block code from the editor, don't hand-write HTML class and style.

  1. Configure the block in the editor
  2. Switch to Code Editor view
  3. Copy the complete block comment + HTML
  4. Paste into Pattern file

Correct example:

<!-- wp:group {"backgroundColor":"accent","borderColor":"neutral-200","style":{"border":{"radius":"8px","width":"1px","style":"solid"}}} -->
<div class="wp-block-group has-border-color has-neutral-200-border-color has-accent-background-color has-background" style="border-width:1px;border-style:solid;border-radius:8px;">
<!-- content -->
</div>
<!-- /wp:group -->

Cause 5: Global Styles Override theme.json

Root Cause

Custom styles saved by Site Editor are stored in wp_global_styles CPT with higher priority than theme.json.

After modifying theme.json, the frontend still shows old values because global styles override theme defaults.

Debug

# Check if global styles exist
wp post list --post_type=wp_global_styles --fields=ID,post_title --allow-root

# View global styles content
wp post get <ID> --fields=post_content --allow-root

Solution

# Delete global styles
wp post delete <ID> --force --allow-root

# Clear cache
wp cache flush --allow-root

Prevention: Avoid using Site Editor for custom styles during development. Manage all configuration through theme.json.


Debug Flow Summary

Block validation failed

├─→ Check if color slugs are defined in theme.json

├─→ Check JSON for duplicate keys

├─→ Check all Style Variations have complete palettes

├─→ Check HTML class/style matches block comments

└─→ Check if wp_global_styles overrides theme.json

Interested in similar projects? Get in touch