Skip to content

Editor: page with Cards Collection queries is dirty on every load — phantom 'unsaved changes' in the Site Editor save panel #543

Description

@georgeolaru

Symptom

Opening the Site Editor (or editor) on the Mies homepage (page 52 on the SM dev site) marks the page entity dirty before any interaction: wp.data.select('core').__experimentalGetDirtyEntityRecords() lists postType/page/52 with edit keys selection, content, blocks on a fresh load. Consequences for every user on this stack: the save panel always shows an extra 'site change' (e.g. '2 site changes' when only Style Manager was edited), and closing the tab warns about unsaved changes the user never made. Reproduced consistently during the Style Manager Site Editor sessions of 2026-06-12.

What's established

  • PHP-side serialization is stable: serialize_blocks( parse_blocks( content ) ) round-trips byte-identical — the normalization happens in the editor's JS layer (block validation / deprecation migration / markup regeneration).
  • The first core/query block on the page carries a non-canonical taxQuery shape: \"taxQuery\":{\"include\":{\"post_tag\":[63]}} (nested include), while core's canonical shape is flat ({\"post_tag\":[63]}) and Nova Blocks' own supernova edit.js consumes the flat shape (Object.entries(taxQuery) → slug → terms). Legacy content from an earlier query-extension era is the prime suspect.
  • Nova Blocks' core/query extension (packages/core/src/blocks/core/query) is edit-UI-only (no schema/save filters) — not a serialization suspect by itself.
  • A Node round-trip harness with registerCoreBlocks() under jsdom hangs (editor-store side effects), so the byte-level diff needs an editor session.

Pinpointing (3 lines in the editor devtools, next session)

const { getEditedEntityRecord, getEntityRecord } = wp.data.select('core');
const edited = wp.blocks.serialize( getEditedEntityRecord('postType','page',52).blocks );
console.log( edited === getEntityRecord('postType','page',52).content.raw ); // find first diff index when false

Suggested direction

Whatever attribute/markup the editor normalizes should get a proper deprecation entry (or a content migration) so parses are stable — silent re-serialization dirt punishes users on every page load. If the nested taxQuery.include shape is ours from an older release, a deprecation that migrates it to the flat shape (or a save filter that tolerates it) removes the dirt at the source.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions