WordPress Gutenberg Editor Won’t Load: A Practical Debug Checklist

Was this helpful?

The Gutenberg editor “loads” the way a bad elevator “arrives”: the doors never open, the spinner keeps spinning, and everyone starts blaming networking like it owes them money.

This guide is for when the block editor won’t load, gets stuck on “Updating…”, shows a blank content area, or throws “The editor has encountered an unexpected error.” We’ll diagnose it like an SRE: isolate variables, prove hypotheses, and change one thing at a time—because production doesn’t care about your vibes.

Fast diagnosis playbook

If you want the fastest path to the bottleneck, stop guessing and run this in order. The point is not “try things.” The point is to identify which layer is lying to you.

1) Check the browser console first (JS errors decide everything)

  • Open the editor page: /wp-admin/post-new.php or /wp-admin/post.php?post=ID&action=edit.
  • DevTools → Console: look for red errors and failed network requests.
  • DevTools → Network: filter by wp-json, rest, block-editor, wp-admin/load-scripts.php, and admin-ajax.php.

Decision: If you see “Failed to fetch”, “Unexpected token < in JSON”, or 401/403/5xx on REST endpoints, this is not a “Gutenberg problem.” It’s an API/auth/WAF/cache problem.

2) Verify REST API works from the server (don’t trust the browser)

Hit /wp-json/ and an authenticated endpoint. If your server can’t reach itself (or returns HTML where JSON should be), Gutenberg will sulk.

Decision: If /wp-json/ is broken, fix that first. Gutenberg depends on it like oxygen depends on lungs.

3) Disable plugins and switch to a default theme (surgical, not emotional)

Do it via WP-CLI so you’re not locked out by the very UI you’re trying to fix.

Decision: If disabling plugins fixes it, re-enable in batches to identify the offender. If theme switch fixes it, hunt for editor scripts, enqueue issues, or CSP headers from the theme.

4) Check caching and security layers (the usual suspects)

  • Object cache (Redis/Memcached)
  • Full-page cache/CDN (Cloudflare, Fastly, varnish, nginx microcache)
  • WAF rules blocking wp-json or admin scripts
  • CSP headers blocking inline scripts used by WordPress

Decision: If editor loads in an incognito window but not normal mode, look for cached assets, service workers, or aggressive browser extensions. If editor loads when bypassing CDN/WAF, your edge config is the villain.

5) Confirm PHP and storage aren’t failing under load

Gutenberg makes more requests than the classic editor. If PHP-FPM is saturated, disk is thrashing, or opcache is misbehaving, the editor looks “stuck” but the real issue is latency and timeouts.

Decision: If server-side logs show 502/504 or timeouts, fix capacity and latency. Debugging WordPress with a dying disk is like tuning a piano during an earthquake.

How Gutenberg actually loads (and how it breaks)

Gutenberg is a JavaScript application embedded inside wp-admin. When you open the editor, WordPress returns an admin page that bootstraps a pile of scripts (React, data stores, block registry, editor UI) and then pulls content and configuration via REST API calls.

That means your failure modes tend to cluster into four buckets:

  1. Bootstrap failures: editor JS/CSS fails to load, or loads corrupted. Typical causes: caching/CDN rewriting, minifiers, mixed content, CSP, wrong content-type.
  2. API failures: wp-json blocked, returning HTML instead of JSON, authentication cookies not accepted, nonce issues, 401/403 from WAF, 5xx from PHP.
  3. Data-layer failures: object cache weirdness, database errors, autoloaded options bloating, slow queries time out.
  4. Environmental failures: PHP memory limit, opcache exhaustion, disk full, permissions, file corruption, or a “helpful” security plugin hardening endpoints.

When the block editor “doesn’t load,” it’s often not a single catastrophic error. It’s a chain: a script fails, then the JS app can’t fetch REST endpoints, then it shows a spinner forever because it’s waiting for a promise that never resolves. Your job is to find the first broken link.

One quote worth keeping on your wall, because it’s annoyingly true: Hope is not a strategy. — General Gordon R. Sullivan.

Joke #1: Gutenberg is a single-page app living in a multi-page world. That’s like putting a race car engine in a shopping cart and acting surprised when it squeaks.

Interesting facts and quick history (why this keeps happening)

  • Gutenberg shipped as a plugin first before being merged into WordPress core, which is why some sites still carry legacy Gutenberg plugin baggage.
  • WordPress 5.0 (2018) made the block editor the default, which suddenly pushed millions of admin environments into a heavier JavaScript workload.
  • The block editor leans hard on the REST API; the classic editor could limp along with fewer dynamic calls.
  • wp-admin historically tolerated “creative” caching setups because most admin pages were server-rendered. Gutenberg punishes incorrect caching much faster.
  • Security plugins started aggressively filtering JSON endpoints as REST-based attacks became common; some rulesets “solve” security by breaking the editor.
  • Nonce and cookie flows changed over time with improvements in admin security, which means old reverse proxies and SSO setups can drift out of compatibility.
  • Many optimization plugins were built for front-end performance; they happily minify and defer scripts in wp-admin unless explicitly configured not to.
  • Block themes and Full Site Editing increased editor surface area (site editor, template parts, global styles). More endpoints. More ways to fail.

First observations: classify the failure in 60 seconds

What does the user see?

  • Infinite spinner / “Loading…” forever: usually REST API call blocked, or JS runtime error early in boot.
  • White screen / blank content area: JS fatal, CSP block, a script 404, or a PHP fatal that outputs HTML into JSON endpoints.
  • “The editor has encountered an unexpected error” with a “Copy error” button: good; it means Gutenberg caught something. Copy it and use it.
  • Editor loads but can’t save / update: often nonce/auth/cookie issues, REST 401/403, or mod_security/WAF blocks POST.
  • Only happens for certain users: role/capability mismatch, usermeta corruption, browser extension, or CDN cookies differing by user group.
  • Only happens on one post: malformed block markup, huge post_content, embedded HTML/shortcodes causing parser choke, or revision meta bloat.

Fast “is it your machine?” sanity checks

  • Try incognito/private window.
  • Try another browser.
  • Disable browser extensions (especially ad blockers and script blockers).

If those fix it, you don’t have a WordPress bug. You have a client-side sabotage situation.

Practical tasks with commands (and decisions)

These tasks assume you have shell access to the server (or container) hosting WordPress. If you don’t, you can still do some checks via your browser and WordPress admin, but your speed will be limited by meetings.

Task 1: Confirm WordPress and plugin versions via WP-CLI

cr0x@server:~$ cd /var/www/html
cr0x@server:/var/www/html$ wp core version
6.6.2
cr0x@server:/var/www/html$ wp plugin list --status=active --fields=name,version
akismet 5.3.3
wp-super-cache 1.12.4
wordfence 7.11.8

What it means: You’re establishing the baseline. Gutenberg behavior depends on core and plugin versions.

Decision: If core is very old (or plugins are), prioritize updating in a staging environment. If you can’t update, you’ll be debugging around known fixed bugs.

Task 2: Check if REST API is reachable from the server

cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/wp-json/
HTTP/2 200
content-type: application/json; charset=UTF-8
cache-control: no-cache, must-revalidate, max-age=0

What it means: 200 and JSON content-type is the happy path.

Decision: If you get 301/302 loops, fix site URL or proxy headers. If content-type is text/html, something is intercepting the endpoint (theme/plugin output, WAF block page, or PHP fatal dumping HTML).

Task 3: Look for REST responses that are actually HTML (classic Gutenberg killer)

cr0x@server:~$ curl -sS https://example.com/wp-json/ | head
{"name":"Example Site","description":"","url":"https:\/\/example.com","home":"https:\/\/example.com","gmt_offset":"0","timezone_string":"UTC"

What it means: JSON starts with {. If it starts with <!doctype html> or <html, you’re not getting JSON.

Decision: If HTML shows up, check for security plugins injecting output, server errors, or an upstream (CDN/WAF) serving a block page.

Task 4: Verify wp-admin scripts are served correctly (status, type, size)

cr0x@server:~$ curl -sS -D- -o /dev/null "https://example.com/wp-admin/load-scripts.php?c=0&load[]=wp-blocks,wp-element,wp-editor"
HTTP/2 200
content-type: application/javascript; charset=UTF-8
cache-control: private, max-age=0, no-store, no-cache, must-revalidate

What it means: Editor scripts must come back as JavaScript, not HTML and not a cached “challenge” page.

Decision: If content-type is wrong, stop. Fix caching/minification/CDN rewriting before you touch WordPress.

Task 5: Check for PHP fatals around the time the editor fails

cr0x@server:~$ sudo tail -n 80 /var/log/php8.2-fpm.log
[27-Dec-2025 10:41:12] WARNING: [pool www] child 2314 said into stderr: "PHP Warning:  Undefined array key "foo" in /var/www/html/wp-content/plugins/some-plugin/plugin.php on line 91"
[27-Dec-2025 10:41:12] WARNING: [pool www] child 2314 said into stderr: "PHP Fatal error:  Uncaught Error: Call to undefined function wp_get_environment_type() in /var/www/html/wp-content/plugins/some-plugin/plugin.php:132"

What it means: Fatal errors can break REST responses and script loaders, causing Gutenberg to fail indirectly.

Decision: If you see fatals, disable the plugin/theme causing them. Don’t “work around” fatals.

Task 6: Check WordPress debug log for REST/editor hints

cr0x@server:~$ sudo tail -n 80 /var/www/html/wp-content/debug.log
[27-Dec-2025 10:41:11 UTC] WordPress database error Deadlock found when trying to get lock; try restarting transaction for query UPDATE `wp_options` SET `option_value` = '...' WHERE `option_name` = '_transient_timeout_wp_core_block_patterns'
[27-Dec-2025 10:41:12 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/some-plugin/plugin.php:91)

What it means: Deadlocks and “headers already sent” frequently translate into broken JSON.

Decision: Fix database contention (or remove the code causing repeated option updates). Fix “headers already sent” by removing stray output, BOMs, or noisy plugins.

Task 7: Disable all plugins quickly (then re-enable in batches)

cr0x@server:~$ cd /var/www/html
cr0x@server:/var/www/html$ wp plugin deactivate --all
Success: Deactivated 27 of 27 plugins.

What it means: You just reduced the problem space dramatically.

Decision: If Gutenberg now loads, re-enable plugins in groups of 3–5 until it breaks. The last batch contains your culprit.

Task 8: Switch to a default theme to remove theme-layer editor customizations

cr0x@server:~$ cd /var/www/html
cr0x@server:/var/www/html$ wp theme list --status=active
+----------------+----------+-----------+---------+
| name           | status   | update    | version |
+----------------+----------+-----------+---------+
| corp-theme     | active   | none      | 4.9.1   |
+----------------+----------+-----------+---------+
cr0x@server:/var/www/html$ wp theme activate twentytwentyfour
Success: Switched to 'Twenty Twenty-Four' theme.

What it means: Many “corporate themes” add admin/editor scripts, block styles, or CSP headers.

Decision: If default theme fixes it, diff what the theme does in functions.php: enqueued scripts, REST filters, security headers, and editor hooks.

Task 9: Validate HTTP status patterns in web server logs (REST endpoints and admin scripts)

cr0x@server:~$ sudo awk '$7 ~ /wp-json|load-scripts.php|admin-ajax.php/ {print $4, $7, $9}' /var/log/nginx/access.log | tail -n 20
[27/Dec/2025:10:41:10 /wp-json/wp/v2/types?context=edit 403
[27/Dec/2025:10:41:10 /wp-admin/load-scripts.php?c=0&load[]=wp-blocks,wp-element,wp-editor 200
[27/Dec/2025:10:41:11 /wp-json/wp/v2/settings 403
[27/Dec/2025:10:41:12 /wp-json/wp/v2/users/me?context=edit 403

What it means: Repeated 403 on /wp-json/wp/v2/* strongly suggests WAF/security plugin/capability misconfig.

Decision: If 403s line up with editor loads, focus on auth, nonces, and security rules—not JS bundles.

Task 10: Check whether your reverse proxy is sending the right scheme/host (common nonce/cookie breakage)

cr0x@server:~$ sudo grep -R "fastcgi_param\|proxy_set_header" -n /etc/nginx/sites-enabled | head -n 40
/etc/nginx/sites-enabled/example.conf:42:proxy_set_header Host $host;
/etc/nginx/sites-enabled/example.conf:43:proxy_set_header X-Forwarded-Proto $scheme;
/etc/nginx/sites-enabled/example.conf:44:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

What it means: If WordPress thinks it’s on HTTP while users are on HTTPS, you get mixed cookies, wrong redirects, and nonce validation failures.

Decision: If you’re behind a load balancer/ingress, confirm X-Forwarded-Proto and WordPress siteurl/home match reality.

Task 11: Check PHP-FPM saturation (latency makes “loading forever” look like a JS problem)

cr0x@server:~$ sudo systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled)
     Active: active (running) since Fri 2025-12-27 08:12:04 UTC; 2h 31min ago
     Status: "Processes active: 42, idle: 0, Requests: 19832, slow: 117"

What it means: “idle: 0” and a rising slow request count indicates saturation. Gutenberg triggers many admin requests; it amplifies bottlenecks.

Decision: If saturated, inspect slow logs, raise FPM children carefully, and address root causes (slow DB, slow disk, heavy plugins) before you just add workers and melt RAM.

Task 12: Check disk space and inode pressure (boring problems cause exciting outages)

cr0x@server:~$ df -h /var/www/html
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p2  100G   96G  4.0G  96% /
cr0x@server:~$ df -i /var/www/html
Filesystem       Inodes  IUsed   IFree IUse% Mounted on
/dev/nvme0n1p2  6553600 6501021 52579   99% /

What it means: Near-full disks or inode exhaustion can break plugin updates, cache writes, session files, and temp files used by PHP.

Decision: If >90% used or inode >95%, treat it as a priority incident: free space, rotate logs, purge caches, and fix growth.

Task 13: Test database responsiveness and check for table lock pain

cr0x@server:~$ mysql -u root -p -e "SHOW FULL PROCESSLIST\G" | sed -n '1,80p'
*************************** 1. row ***************************
     Id: 1432
   User: wpuser
   Host: 127.0.0.1:59314
     db: wordpress
Command: Query
   Time: 18
  State: Sending data
   Info: SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'

What it means: Long-running queries on wp_options (autoload) are a classic admin slowness vector. Gutenberg will feel “broken” when it’s merely timing out.

Decision: If options autoload query is slow, audit autoloaded options size, remove junk, and fix plugins that spam options.

Task 14: Check autoloaded options size (the invisible anchor)

cr0x@server:~$ mysql -u root -p wordpress -e "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS autoload_mb FROM wp_options WHERE autoload='yes';"
autoload_mb
12.47

What it means: Autoloaded options are loaded on every request. Double-digit MB is not “fine.” It’s a latency tax.

Decision: If autoload is large, identify top offenders and disable/fix the plugins adding huge autoload entries.

Task 15: Identify the biggest autoloaded options (find the plugin doing it)

cr0x@server:~$ mysql -u root -p wordpress -e "SELECT option_name, ROUND(LENGTH(option_value)/1024,1) AS kb FROM wp_options WHERE autoload='yes' ORDER BY LENGTH(option_value) DESC LIMIT 15;"
option_name	kb
some_plugin_cache	2048.0
theme_mods_corp-theme	1536.4
wpseo_titles	412.7

What it means: You now have names. Names are actionable.

Decision: For huge plugin cache options, switch them to non-autoload or purge. For theme mods, consider whether the theme is storing too much and whether the site editor is amplifying it.

Task 16: Temporarily bypass object cache to see if Redis/Memcached is poisoning admin

cr0x@server:~$ cd /var/www/html/wp-content
cr0x@server:/var/www/html/wp-content$ ls -l object-cache.php
-rw-r--r-- 1 www-data www-data  48210 Dec 10 09:14 object-cache.php
cr0x@server:/var/www/html/wp-content$ sudo mv object-cache.php object-cache.php.disabled

What it means: WordPress uses wp-content/object-cache.php as a drop-in. Renaming disables it.

Decision: If Gutenberg works after disabling object cache, your cache backend or drop-in is buggy/misconfigured. Fix it; don’t leave cache disabled forever unless you like expensive database bills.

Task 17: Confirm headers aren’t blocking scripts (CSP is a frequent self-own)

cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/wp-admin/post-new.php | egrep -i "content-security-policy|x-frame-options|x-content-type-options"
content-security-policy: default-src 'self'; script-src 'self'; object-src 'none'
x-content-type-options: nosniff

What it means: A strict script-src 'self' can break WordPress admin because core relies on inline scripts in places (and on dynamically loaded chunks).

Decision: If CSP is strict, adjust it specifically for wp-admin (or remove it there). Security is good; breaking your editor is not “secure,” it’s just inconvenient.

Task 18: Check for mixed content or forced HTTP in WordPress config

cr0x@server:~$ wp option get siteurl
https://example.com
cr0x@server:~$ wp option get home
https://example.com

What it means: If these are HTTP while your admin is HTTPS, you’ll get asset mismatches and cookie weirdness.

Decision: Fix siteurl/home and proxy headers. Then clear caches.

Common mistakes: symptom → root cause → fix

1) Symptom: Infinite “Loading…” spinner in the editor

Root cause: REST API calls returning 403 (WAF/security plugin) or returning HTML instead of JSON.

Fix: Verify /wp-json/ and /wp-json/wp/v2/users/me?context=edit in DevTools Network. Whitelist REST endpoints in WAF, adjust security plugin rules, or fix PHP fatals producing HTML output.

2) Symptom: “The editor has encountered an unexpected error” after a plugin update

Root cause: Plugin enqueues scripts in wp-admin incorrectly (wrong dependencies, conflicting React, or global variable clobbering).

Fix: Disable the plugin. If you must keep it, ensure it doesn’t ship its own React or bundle WordPress packages incorrectly; update to a compatible version.

3) Symptom: Editor works for admins, fails for editors/authors

Root cause: Capability/role restrictions blocking REST endpoints with context=edit, often via membership plugins or custom code.

Fix: Compare REST responses by role. Fix capability mapping and don’t blanket-block wp/v2 endpoints.

4) Symptom: Editor loads only in incognito

Root cause: Browser extensions, cached broken assets, or service worker interference.

Fix: Disable extensions, clear site data, and ensure admin assets aren’t cached by CDN. Verify cache-control on load-scripts.php is private/no-store.

5) Symptom: “Updating failed. The response is not a valid JSON response.”

Root cause: REST save call returns HTML (PHP warning output, WAF block page, or 500 error page).

Fix: Look at the failed network request response body. Fix the PHP warning/fatal, disable the plugin printing output, or whitelist the endpoint in WAF.

6) Symptom: Gutenberg only breaks on big posts

Root cause: Huge post_content, many blocks, heavy shortcodes, or memory exhaustion during parse/render of block markup.

Fix: Increase PHP memory and max execution time cautiously, remove pathological blocks/shortcodes, split content, and clean revisions.

7) Symptom: Editor broken right after “performance optimization”

Root cause: Minify/defer plugin applies to wp-admin, or CDN caches wp-admin/load-scripts.php.

Fix: Exclude wp-admin and load-scripts.php from optimization. Ensure edge respects private/no-store headers for admin.

8) Symptom: Random failures, especially under load

Root cause: PHP-FPM saturation, slow DB, object cache instability, disk latency, or inode exhaustion.

Fix: Treat as performance incident: check FPM status, slow logs, DB processlist, disk space/inodes. Fix capacity and hotspots.

Checklists / step-by-step plan

Checklist A: Debug Gutenberg not loading (15–30 minutes)

  1. Browser console: capture the first red error. Not the tenth. The first one usually matters.
  2. Network tab: identify the first failing request (often /wp-json/, /wp-json/wp/v2/settings, or /wp-admin/load-scripts.php).
  3. Confirm on server: curl the failing endpoint and verify status and content-type.
  4. Disable plugins: wp plugin deactivate --all.
  5. Switch theme: activate a default theme temporarily.
  6. Bypass caches: disable object cache drop-in; bypass CDN if possible (direct origin host header or internal VIP route).
  7. Check logs: PHP-FPM log + web error log + WordPress debug log.
  8. Restore incrementally: re-enable plugins in batches, then theme, then caches.

Checklist B: When saving fails but editor loads

  1. In DevTools, find the failing save request (often POST to /wp-json/wp/v2/posts/ID).
  2. Inspect response body: is it HTML (error page), JSON (with error code), or empty?
  3. Check auth headers/cookies: is the user logged in? Any SSO or reverse proxy rewriting cookies?
  4. Check server logs for 401/403/500 on that request time.
  5. Temporarily disable WAF rule sets affecting POST/JSON endpoints.
  6. Confirm nonce generation isn’t cached (admin pages should not be cached).

Checklist C: Performance-induced “won’t load” (because timeouts look like bugs)

  1. Check PHP-FPM active/idle, slow requests, and timeouts.
  2. Check DB: long queries, table locks, and autoload size.
  3. Check disk: space, inodes, and I/O latency symptoms (queue depth, high await).
  4. Disable the heaviest admin plugins first (page builders, analytics dashboards, security scanners).
  5. Only then tweak timeouts/memory. Increasing limits without fixing slowness just extends the suffering.

Joke #2: When someone says “I didn’t change anything,” I assume they mean “I changed something and didn’t write it down.”

Three corporate mini-stories from the trenches

Mini-story 1: The incident caused by a wrong assumption

A mid-sized company ran WordPress behind a load balancer and an nginx reverse proxy. The migration was “simple”: move traffic, keep the origin the same, call it a win. The editor promptly started hanging for some users, but not all. Naturally, the first theory was “Gutenberg is flaky.”

The clue was in the network trace: REST calls to /wp-json/wp/v2/users/me?context=edit returned 401 for some sessions. Same user, different results depending on which proxy node they hit. That smells like cookies.

They assumed the app would infer HTTPS correctly because “the load balancer terminates TLS.” WordPress didn’t care about that assumption. It cared about what it saw: requests arriving to the origin as HTTP, and WordPress generating cookies/nonces with behavior mismatched to the browser’s HTTPS reality.

The fix wasn’t mystical. They set X-Forwarded-Proto properly, ensured WordPress honored it, and corrected siteurl/home. The editor recovered instantly, and the postmortem conclusion was painfully ordinary: the system did exactly what it was configured to do, not what people believed it was doing.

Mini-story 2: The optimization that backfired

A different org wanted faster admin performance and deployed a “smart cache” rule at the CDN: cache any request with a 200 response and “static-looking” query parameters. Someone noticed that load-scripts.php and load-styles.php looked like static assets. They were wrong in the way that causes Monday morning pages.

For a while, it seemed fine. Then a WordPress minor update landed. The cached admin script bundle didn’t match the new server-side expectations, and suddenly Gutenberg began failing with JS errors that referenced missing modules and undefined functions.

Engineers chased ghosts: plugin conflicts, theme issues, browser bugs. The tell was that the error only happened for users served by the CDN edge cache, and it disappeared when bypassing the edge. The cached response headers were also suspiciously “public.”

The fix: never cache wp-admin script loaders at the CDN, respect WordPress’s private/no-store semantics, and don’t treat query-string assets as safe just because they resemble them. The “optimization” was rolled back, and admin became boring again—which is the correct performance state for a CMS backend.

Mini-story 3: The boring but correct practice that saved the day

An enterprise site had a standing operational rule: every change touching caching, WAF, or reverse proxy headers had to include a pre-flight test against three endpoints—/wp-json/, /wp-admin/load-scripts.php, and an authenticated REST call. Not glamorous. Not optional.

One afternoon, a security team pushed a new WAF policy to reduce bot traffic. It blocked requests that looked like “API enumeration,” which included some REST routes used by authenticated admin screens. The CMS team didn’t notice immediately because front-end pages still rendered.

But the pre-flight test, run from a CI job using a low-privilege editor account, failed within minutes. The failure report included HTTP status codes and response snippets. That meant the CMS team didn’t have to argue about whether Gutenberg was “down”; they had evidence.

The WAF policy was adjusted with a targeted allow rule for authenticated wp-json traffic, and the incident stayed small. The moral is annoyingly predictable: the boring checks you automate are the ones that save you when humans get creative.

FAQ

1) Why does Gutenberg depend on the REST API so much?

Because it’s a JavaScript app that fetches and saves content via API routes. If /wp-json/ is blocked, Gutenberg can’t load post data, settings, user info, or save operations reliably.

2) The editor works on my laptop but not for colleagues. What’s the first suspect?

Caching and security layers that vary by geography, cookie, or IP. CDN edge behavior, WAF challenges, or corporate proxies can selectively break wp-admin requests.

3) Can a single PHP warning really break the editor?

Yes. If a warning prints output during a REST response, your JSON becomes “JSON plus noise,” and Gutenberg treats it as invalid. Fix the warning or suppress output properly—don’t just hide it.

4) Should I just install the Classic Editor plugin and move on?

Only as a temporary mitigation. It can keep editors working while you fix the underlying REST/caching/security issue. If you treat it as the permanent fix, you’re paying interest on a problem.

5) What’s the fastest way to prove it’s a plugin conflict?

Disable all plugins via WP-CLI and retest. If it works, re-enable in batches. It’s faster than reading plugin code and pretending you enjoy it.

6) Could my database be the reason Gutenberg won’t load?

Absolutely. Slow autoloaded options, deadlocks, or long-running queries can delay REST responses until the UI times out or appears frozen. Check processlist and autoload size.

7) Does object caching help or hurt Gutenberg?

Both. Correctly configured object cache reduces DB load and speeds admin. Misconfigured or buggy drop-ins can return stale/incorrect data, break nonces, or produce inconsistent behavior. Temporarily disable to isolate.

8) I get 403 on wp-json routes only in wp-admin. Why?

Because authenticated REST calls include cookies and nonces, and security layers often treat them differently. WAF rules that are fine for anonymous GETs can block authenticated API routes used by the editor.

9) Is CSP in wp-admin a bad idea?

Not inherently, but it’s easy to do wrong. If you set a strict policy without accommodating WordPress admin’s script patterns, you’ll block core functionality. Apply CSP carefully and test the editor.

10) My site is on multisite. Any special Gutenberg failure modes?

Yes: domain mapping mismatches, cookie scope issues across subdomains, and network-activated plugins affecting REST behavior. Test the REST API and editor on multiple subsites and roles.

Next steps you can do today

  1. Prove the layer: browser console + network tab, then curl the same endpoints from the server.
  2. Make REST boring: ensure /wp-json/ returns JSON with 200, not redirects, not HTML, not WAF theater.
  3. Isolate variables: disable plugins, switch to a default theme, bypass object cache, bypass CDN/WAF.
  4. Fix the boring infrastructure issues: PHP-FPM saturation, disk pressure, DB autoload bloat, and mis-set proxy headers.
  5. Lock in prevention: add a simple automated check that hits REST and admin script endpoints after changes to caching/WAF/proxy.

If you do those in that order, you’ll stop “debugging Gutenberg” and start fixing the actual system that Gutenberg is merely revealing. And that’s the whole game.

← Previous
Unsigned drivers: when security broke perfectly fine hardware
Next →
Ubuntu 24.04 “Illegal instruction”: CPU flags vs binaries — fix deployments cleanly (case #56)

Leave a comment