Confirmed: high-severity content-integrity bug in Create Block Theme 2.10.1.
Terminology: ordinary “unsynced patterns” are normally copied inline and do not retain database IDs. The broken references are usually instances of synced patterns that become dangling after their wp_block source is deleted.
- Save Patterns is enabled by default in
src/editor-sidebar/save-panel.js:168-178. /savecallsCBT_Theme_Patterns::add_patterns_to_theme()atincludes/class-create-block-theme-api.php:395-400.- Each
wp_blockis written topatterns/*.php. replace_local_pattern_references()only searcheswp_templateandwp_template_partattheme-patterns.php:132-150.- It replaces references only in theme pattern/template files at
theme-patterns.php:152-163. - Ordinary posts, pages and CPTs retain
<!-- wp:block {"ref":ID} /-->. - The source is permanently deleted with
wp_delete_post( $pattern->id, true )attheme-patterns.php:248-249. - Core subsequently calls
get_post( ID ); if absent,core/blockrenders nothing and the editor reports “Block has been deleted or is unavailable.”
The deletion boundary assumes every caller belongs to a theme template. That assumption is false: synced patterns can be inserted into any post type with block content.
The original implementation in PR #675 covered only template references. PR #790 later removed the sync-status distinction and made deletion unconditional for all patterns. No test asserts referential integrity in posts/pages; the existing integration test explicitly accepts source deletion.
- Exact
str_replace()only handles canonicalwp:block {"ref":ID}markup. It misses extra attributes, spacing and pattern overrides. template-parts/*.htmlis hard-coded, while current WordPress returnsparts/fromget_block_theme_folders().- Files are written and sources deleted incrementally; failures can leave a partial migration.
- Filesystem writes and
wp_delete_post()results are not checked. sanitize_title_with_dashes()creates percent-encoded pattern slugs under the Finnish locale; the current site emits invalid-slug notices. This is adjacent but should be fixed before slug migration is trusted.
The read-only audit found:
- 5 broken references
- 17 affected URLs
- Includes draft page
34228, templates and template parts - Parent plugin: Create Block Theme
2.10.1, WordPress7.0.2
No data was changed.
wpcli-create-block-theme.php:
- Records ID→theme-slug mappings before parent save deletes the rows.
- Runs the parent save.
- Scans every non-revision post afterward and changes ID references to
core/patternslug references. - Retains the mapping for interrupted-save repair.
This protects only saves performed through its WP-CLI command. The Site Editor’s native /save path remains vulnerable.
It should not be transplanted unchanged because it:
- Runs after destructive deletion.
- Uses the same fragile exact-string replacement.
- Cannot preserve pattern override attributes.
- Converts DB-synced patterns into theme patterns, changing their semantics and making post content dependent on the active theme.
The safest immediate upstream fix is not to delete DB-backed synced patterns until WordPress supports file-backed synced patterns (Gutenberg #59272).
- Restore
wp_pattern_sync_statusto the pattern model. - Continue exporting files.
- Restrict existing ID→slug conversion to theme-owned files.
- Delete only genuinely unsynced patterns.
- Keep synced and partially-synced
wp_blockrows so post/page/CPT references and overrides remain valid. - Replace the hard-coded
template-partspath withget_block_theme_folders(). - Update the Save Patterns help text to explain that synced patterns remain database-backed.
- Add regression tests:
- Synced pattern referenced by page remains renderable.
- Draft/private/custom-post callers remain valid.
- Partial-sync overrides survive.
- Unsynced patterns still export and delete.
- Template-part handling uses
parts/. - Failed writes never delete source posts.
This is the smallest root-cause fix and preserves content semantics.
To integrate the wrapper’s exact behavior natively:
- Put it in
CBT_Theme_Patterns, not REST, CLI, or the proposedCBT_Theme_Saveservice, so every caller shares it. - Build the complete ID→slug map before modifying anything.
- Write and validate all pattern files.
- Parse blocks recursively and migrate every non-revision post type using
wp_update_post()—no rawstr_replace(). - Reject references carrying
content/overrides; retain theirwp_blocksource because conversion would lose data. - Migrate actual template directories returned by
get_block_theme_folders(). - Verify no old references remain in database content or generated files.
- Only then delete source
wp_blockposts. - Add page, post, CPT, nested-reference, multiple-reference, formatting and failure-path tests.
- Make the UI explicitly say this converts synced patterns into theme patterns.
Existing broken references cannot be repaired automatically because their ID→slug mapping is already gone. Keep the workaround’s explicit-map/backup recovery tooling separate from the prevention PR.
Implementation should be made against the upstream repository: ../create-block-theme is a v2.10.1 distribution directory whose Git root is the unrelated VVV site repository.