What this problem looks like
WordPress admin relies on AJAX for autosave, media uploads, and plugin settings. A 400 response often means bad nonce or blocked request. A 500 means PHP fatals in a plugin hook during the AJAX action.
Start in browser DevTools Network tab. The response body often contains -1 for failed nonce or a PHP error string when WP_DEBUG_DISPLAY is on in staging.
Step 1: Inspect admin-ajax.php in DevTools
In Chrome or Firefox, open DevTools → Network. Trigger the broken action, filter by admin-ajax.php, and click the request. Check Status, Response, and Payload tabs.
- 403: security plugin or mod_security blocking POST.
- 500: PHP fatal in a plugin handling the action.
- 200 with body -1: nonce or cookie/session problem.
- 0 or failed: mixed content or wrong admin URL.
Step 2: Enable logging for AJAX fatals
Add debug constants to wp-config.php and reproduce the action. Check wp-content/debug.log immediately after.
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'SCRIPT_DEBUG', true );
Step 3: Re-save permalinks and clear cache
Go to Settings → Permalinks and click Save without changes. This regenerates rewrite rules that admin-ajax relies on. Clear object cache, page cache, and CDN cache after URL or SSL changes.
Step 4: Test for plugin conflicts
Deactivate caching, security, and optimisation plugins first. They hook early into admin-ajax. If using Query Monitor on staging, watch ajax hooks for slow or failing callbacks.
wp plugin deactivate --all
wp plugin activate woocommerce
Step 5: Fix security and CORS blocks
If a security plugin blocks admin-ajax.php, whitelist /wp-admin/admin-ajax.php in its settings or temporarily deactivate via FTP. Ensure admin loads on the same domain as siteurl, not a mismatched www variant.
When to stop DIY and hire help
AJAX failures that only happen on production with a full plugin stack are tedious to bisect. BugShield fixes admin-ajax and editor errors at a fixed price with staging-safe conflict testing.