Skip to content

Fix site editor crash when query loop has multiple post-templates#25

Open
mattheu wants to merge 1 commit into
mainfrom
fix/null-getblock-crash-in-post-template-styles
Open

Fix site editor crash when query loop has multiple post-templates#25
mattheu wants to merge 1 commit into
mainfrom
fix/null-getblock-crash-in-post-template-styles

Conversation

@mattheu

@mattheu mattheu commented Jul 8, 2026

Copy link
Copy Markdown
Member

Problem

Opening any template in the site editor that contains a pattern with a core/query block having two or more core/post-template children crashes the editor with a TypeError. The AGBI opinion archive template reproduces this via the editors-pick-opinion pattern, which uses a two-column layout (1 featured card + 4 grid cards) inside a single query.

Root cause

withQueryLoopContextProvider populates UsedPostsContext by calling:

return childPostTemplatesClientIds.map( getBlock );

getBlock() can transiently return null in the site editor when a pattern block's inner blocks are registered in the block-name index before their full record is written to byClientId (the two store structures are updated in separate microtasks during initial block-tree construction). This leaves null values in the postTemplates array.

Both withPostTemplateStyles and withPostTemplateInspectorControls then iterate postTemplates and access postTemplate.clientId without a null guard — throwing TypeError: Cannot read properties of null (reading 'clientId') and crashing the editor.

This was masked in ≤ 0.4.x because withUniqueQueryId always called setAttributes on first render, forcing a store update + re-render cycle that resolved the transient null state before any consumer ran. The 0.7.0 fix (preserve unique queryIds) eliminated that forced re-render, exposing the latent race.

Fix

  1. Filter nulls from getBlock() results in withQueryLoopContextProvider so consumers always receive valid block objects:

    return childPostTemplatesClientIds.map( getBlock ).filter( Boolean );
  2. Guard the hideAfterLimit CSS rule against perPage = undefined: without a perPage limit the expression offset + undefined + 2 evaluates to NaN, producing the invalid selector nth-of-type(n+NaN). Suppress the rule entirely when no limit is set (correct behaviour — if there's no limit, no posts should be hidden).

Testing

  • Open the site editor and edit a template that embeds a pattern containing a core/query with two core/post-template children
  • Editor should load without crashing
  • Inspector controls for each post-template should show correctly
  • Post-template CSS offset/limiting should still function for templates where perPage is set

🤖 Generated with Claude Code

getBlock() can transiently return null in the site editor when a
template includes a pattern block whose inner blocks land in the name
index before their full record exists in byClientId. The resulting
null in the postTemplates array crashed withPostTemplateStyles and
withPostTemplateInspectorControls when they accessed
postTemplate.clientId.

Fix: filter nulls out of the getBlock() results in
withQueryLoopContextProvider so consumers always receive valid block
objects.

Also fixes a secondary issue: when perPage is undefined (no limit
set on a post-template) the hideAfterLimit CSS rule evaluated to
nth-of-type(n+NaN), an invalid selector. Suppress the rule entirely
when perPage is not set — no limit means no posts should be hidden.

Reproducer: open the site editor and edit any template that embeds a
pattern containing a core/query block with two core/post-template
children (e.g. the editors-pick-opinion pattern on an AGBI opinion
archive template).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Playwright test results

passed  19 passed

Details

stats  19 tests across 6 suites
duration  1 minute, 18 seconds
commit  9603440

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant