The Problem
A client running a multi-location franchise site updated to WordPress 7.0 last weekend. Every location page uses a shared synced pattern for the hero — same layout, different headline and image per branch, wired up with pattern overrides. After the update, editors started reporting that the per-page text was reverting back to the source pattern's default the moment they hit save. Re-edit, save, refresh — gone again.
The pattern looked correct in the editor. Overrides were toggled on. The block markup in the database had the right metadata.bindings block, but the override values were missing from the post content. In the rendered front-end, every location page showed the same default headline.
This is what the saved block markup looked like for an affected heading:
<!-- wp:heading {"metadata":{"bindings":{"content":{"source":"core/pattern-overrides"}}}} -->
<h2 class="wp-block-heading">Default headline from pattern</h2>
<!-- /wp:heading -->
What it should have looked like, with the override actually stored:
<!-- wp:heading {"metadata":{"name":"hero-heading","bindings":{"content":{"source":"core/pattern-overrides"}}}} -->
<h2 class="wp-block-heading">Default headline from pattern</h2>
<!-- /wp:heading -->
Spot the difference? The metadata.name attribute is gone on the broken version. WordPress 7 tightened the override resolver and now requires every overridable block in the source pattern to have a unique, stable metadata.name. If it does not, the override on the consuming post is silently dropped at save time. No console warning. No notice in the editor. Just data loss.
Why It Happens
Pattern overrides have always worked by matching child blocks between the source pattern and the consuming instance. In 6.6 through 6.9, that match was best-effort — block type plus position plus binding source was usually enough to identify which child block on the instance corresponded to which child block on the source. If the editor could not find a stable identifier, it would fall back to position-based matching, which mostly worked.
WordPress 7.0 removed the positional fallback. The pattern overrides specification now treats metadata.name as the required join key. Two reasons. First, positional matching was fragile — adding a paragraph above a heading in the source pattern silently broke every override that targeted that heading. Second, the new collaborative editing work in 7.x needs stable block identities to merge concurrent edits without clobbering each other.
The breakage on existing sites is not a regression. It is the cost of finally making overrides safe to use across pattern revisions. The problem is that the migration is one-way: patterns built in 6.x rarely set metadata.name because the editor did not require it, and existing override data on consuming posts is keyed against blocks that no longer have a stable name to match against.
I ran into this on a client project where the franchise pattern had been authored in WordPress 6.7 and shipped untouched through three minor updates. Every site that updated to 7.0 lost its overrides on the next save, including the ones the editor had not touched — opening a page and clicking save was enough to trigger the drop.
The Fix
Two parts. Fix the source pattern, then re-save the consuming posts.
Step 1: Add metadata.name to every overridable block in the source pattern. Open the synced pattern in the Site Editor, click each block that has a binding, expand the Advanced panel in the sidebar, and set the Block Name field. It must be unique within the pattern. I use kebab-case names that describe the role, not the content: hero-heading, hero-image, cta-button-label.
If you have more than a handful of patterns, do it in PHP instead. Patterns registered through register_block_pattern can be updated by editing the pattern source file directly:
register_block_pattern(
'mytheme/location-hero',
array(
'title' => __( 'Location Hero', 'mytheme' ),
'content' => '<!-- wp:heading {"metadata":{"name":"hero-heading","bindings":{"content":{"source":"core/pattern-overrides"}}}} -->
<h2 class="wp-block-heading">Welcome to our store</h2>
<!-- /wp:heading -->
<!-- wp:image {"metadata":{"name":"hero-image","bindings":{"url":{"source":"core/pattern-overrides"},"alt":{"source":"core/pattern-overrides"}}}} -->
<figure class="wp-block-image"><img src="" alt=""/></figure>
<!-- /wp:image -->',
)
);
The metadata.name must be present on the source pattern before any consuming post saves, or the override resolver has nothing to match against.
Step 2: Re-apply overrides on consuming posts. Existing override data is gone. You cannot recover it from the database because WordPress 7 stripped it the first time each post was saved. If you have a recent backup of the wp_posts table from before the update, you can grep the post_content column for core/pattern-overrides and pull the values back manually. Otherwise, editors need to re-enter the per-page content.
To bulk-detect which posts are affected, run this against your database:
SELECT ID, post_title
FROM wp_posts
WHERE post_status = 'publish'
AND post_content LIKE '%core/pattern-overrides%'
ORDER BY post_modified DESC;
Cross-reference the results with your pattern usage to find which posts need attention. On a 400-page franchise site this took about a day of editor time, far less than the SEO damage of leaving every location page showing the same default copy.
Step 3: Add a wp_kses allowlist if your editors use custom HTML. Pattern overrides on core/html blocks were also tightened in 7.0, and some inline attributes that used to round-trip cleanly are now stripped. If you rely on overrides for raw HTML, register the attributes you need through the wp_kses_allowed_html filter before relying on them.
Verify each fixed pattern by opening a consuming post, editing one override, saving, reloading, and confirming the value persisted. If the pattern has more than three overrides, test each one — the resolver fails per-block, not per-pattern, so half can save correctly while the other half silently drops.
The Lesson
WordPress 7 made metadata.name mandatory for pattern overrides. Patterns authored without it look fine in the editor but lose every override the moment a consuming post is saved. Set unique names on every overridable block, redeploy the pattern, and accept that existing override data is gone. The fix is small, but the audit to find every affected post is not.
If your WordPress 7 update wiped out content across a multi-page site and you need help recovering it, that is a project I take on. See my services. For another WordPress 7 gotcha that hit the same release, read WordPress 7 block apiVersion iframe issue.
Lost data after a WordPress 7 upgrade? Get a recovery plan.