Block bugs cluster in three places: edit/save mismatches, stale attributes after schema changes, and styles that look right in the editor but wrong on the front-end. This tutorial covers the tools and habits that catch them.
Block validation — the yellow warning
When you load a post, WordPress parses the saved HTML and reconstructs blocks. If the reconstruction doesn’t match what your Save function would produce now, you get a “Block validation failed” warning with options to “Attempt block recovery” or “Convert to HTML”.
Causes, in order of frequency:
- You changed the Save function without registering a deprecation
- Save uses different markup than what the parser expects (whitespace, attribute order, missing classes)
- An attribute changed sources (was in comment, now in HTML, or vice versa)
The fix is always one of:
- Register a deprecation for the old version
- Make your Save function output identical HTML to what’s saved
- Force re-save by editing and saving the post
React DevTools
Install the React Developer Tools browser extension. With it:
- Inspect the Edit component tree for any selected block
- See current attribute values in the Props panel
- Trigger re-renders to confirm state updates
- Profile editor performance
WordPress ships React in development mode, so DevTools just works — no config needed.
Unit tests with @wordpress/scripts
@wordpress/scripts includes Jest pre-configured. Write tests for pure functions inside your block — attribute transformers, utility functions, render helpers:
// src/utils.js
export function classNameForType(type) {
return `my-callout-${type}`;
}
// src/utils.test.js
import { classNameForType } from './utils';
test('classNameForType prepends my-callout-', () => {
expect(classNameForType('warning')).toBe('my-callout-warning');
});
End-to-end tests with Playwright
For full block-in-editor flows, @wordpress/e2e-test-utils-playwright provides helpers. These tests run a real WordPress + Chrome:
import { test, expect } from '@wordpress/e2e-test-utils-playwright';
test('Callout block inserts and saves', async ({ admin, editor }) => {
await admin.createNewPost();
await editor.insertBlock({ name: 'my-first-block/callout' });
await editor.setBlockAttribute('title', 'Test title');
await editor.publishPost();
await expect(editor.canvas.getByText('Test title')).toBeVisible();
});
E2E tests are slow but catch the issues unit tests miss — actual editor interactions, attribute persistence, save/load cycles.
Common pitfalls + fixes
| Symptom | Likely cause |
|---|---|
| Yellow “Block validation failed” | Save function changed since content was saved. Add a deprecation. |
| Block disappears after save | Save returned null without render callback set. Either return JSX or wire dynamic render. |
| Styles look right in editor, wrong on front-end | editor.scss styles aren’t loaded on front-end (correct), but you put real styles there. Move to style.scss. |
attributes is undefined | Forgot to declare in block.json. Add it. |
setAttributes is not a function | Typo or trying to call from Save. Save doesn’t have setAttributes. |
| Block doesn’t appear in inserter | Build didn’t run, or stale browser cache. npm run build + hard refresh. |
| Editor crashes when block is selected | React error inside Edit. Open browser console for the stack trace. |
| Edit looks like raw text, not the component | index.js didn’t register the block. Check npm run start output for errors. |
Debugging workflow
When something breaks:
- Open browser DevTools console — most block errors throw there before they affect the UI
- Check
npm run startoutput — webpack errors show up here, not in the browser - Inspect the block in the React DevTools — confirm attributes match what you expect
- Switch to Code editor view (top-right menu) — see the actual saved HTML
- Try with all other plugins deactivated — to rule out conflicts
- Diff the rendered HTML against what Save would output now — for validation issues
What’s next
Part 12 is the finale — publishing your block plugin to wordpress.org so other people can install it.
Get the next one in your inbox. Practical tips, no fluff.
More tutorials
View all-
Block Patterns
Register reusable block compositions — landing-page hero, feature grid, FAQ section — that users insert as a complete unit.
25 min
-
Block Attributes and Serialization
Master the attribute system — types, sources, defaults, and how block data round-trips between the editor, the database, and the front-end.
30 min
-
Building a Block Plugin
Package your block as a proper WordPress plugin — file structure, asset enqueueing, server-side render callbacks, plugin metadata.
35 min