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- WordPress
How to Prepare Your Plugin or Theme for WordPress 7.1
A WordPress 7.1 compatibility checklist: iframed editor, client-side media hooks, Abilities public flag, jQuery UI 1.14.2, plus features that did not ship (React 19, collaboration).
22 min
- WordPress
What's New in WordPress 7.1 for Developers
WordPress 7.1 field guide for developers: client-side media, Abilities API, always-iframed editor, SVG Icon API, global styles, and what to test before users upgrade.
18 min
- WordPress
Abilities API Changes in WordPress 7.1
WordPress 7.1 upgrades the Abilities API: a unified public flag, wp_get_abilities() filtering, execution lifecycle hooks, JSON Schema for clients, and typed REST input.
25 min