Troubleshooting WordPress AJAX 400 Error
I’m encountering a 400 error (strict-origin-when-cross-origin) with my WordPress AJAX implementation despite following standard practices. Here’s my code:
Plugin Setup
require_once( plugin_dir_path( __FILE__ ) . 'classes/duplicate_statement_controller.class.php' );
add_action( 'wp_enqueue_scripts', function(){
wp_enqueue_style('duplicate-tax-css' , plugin_dir_url( __FILE__ ) . '/assets/duplicate-tax.css' );
wp_enqueue_script( 'duplicate-tax-js', plugin_dir_url( __FILE__ ) . '/assets/duplicate-tax.js', array('jquery'), '1.0', true );
wp_localize_script( 'duplicate-tax-js', 'tax_object',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce('tax-nonce')
)
);
} );
jQuery AJAX Call
$.ajax({
url: tax_object.ajax_url,
type: 'post',
data: {
action: 'add_row',
nonce: tax_object.nonce
},
success: function (response) {
// probably re-calc here
console.log(response);
}
});
PHP AJAX Handler
private function __construct() {
//Wordpress hooks and filters
add_action( 'init', array ( $this , 'action_init' ) );
// Ajax actions for rows
add_action('wp_ajax_add_row', array( $this , 'add_row' ) );
add_action('wp_ajax_nopriv_add_row', array( $this , 'add_row' ) );
add_action('wp_ajax_remove_row', array( $this , 'remove_row' ) );
add_action('wp_ajax_nopriv_remove_row', array( $this , 'remove_row' ) );
}
public function add_row() {
error_log("!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
Problem Description
Every time I run this, I get a 400 error (strict-origin-when-cross-origin). I’ve registered the AJAX calls, used wp_enqueue and wp_localize_script, and included both wp_ajax and wp_ajax_nopriv hooks as recommended. The syntax appears correct, and this same code works in another plugin without issues.
What could be causing this 400 error, and how can I troubleshoot it further?
The WordPress AJAX 400 error with “strict-origin-when-cross-origin” indicates both a server-side 400 Bad Request response and a client-side CORS policy issue. This combination suggests your AJAX request isn’t reaching the server properly due to browser security restrictions, or the server is rejecting the request for specific reasons.
Based on your code and the research findings, here’s a comprehensive troubleshooting guide:
Contents
- Understanding the Error Combination
- Common Causes and Solutions
- Step-by-Step Troubleshooting
- Advanced CORS Configuration
- Plugin and Theme Conflicts
- Alternative Approaches
Understanding the Error Combination
The “400 error (strict-origin-when-cross-origin)” is actually two separate issues combined:
- 400 Bad Request: Server-side error indicating the request format is incorrect
- strict-origin-when-cross-origin: Browser security policy preventing cross-origin requests
As noted in the research findings, “that’s not one single error, that’s two.” The browser is likely blocking the request before it even reaches your server, or the server is rejecting it with a 400 status code.
Common Causes and Solutions
1. Action Parameter Issues
The most common cause of WordPress AJAX 400 errors is missing or incorrect action parameters:
// Your current code
data: {
action: 'add_row',
nonce: tax_object.nonce
}
Solution: Ensure the action parameter exactly matches what you registered. Double-check for typos and case sensitivity.
2. Content-Type Mismatch
Based on the research findings, the old admin-ajax.php endpoint doesn’t support JSON payloads:
“the contentType part in your JS script, which submits the form data as a JSON payload, but note that the old admin-ajax.php endpoint doesn’t support JSON payload, hence $_REQUEST[‘action’] would be empty”
Solution: Remove any contentType: 'application/json' from your AJAX call and let jQuery use the default application/x-www-form-urlencoded:
$.ajax({
url: tax_object.ajax_url,
type: 'post',
data: {
action: 'add_row',
nonce: tax_object.nonce
},
// Remove contentType setting entirely
success: function (response) {
console.log(response);
}
});
3. Hook Registration Timing
Your hooks are registered in the constructor, but they might be too late:
private function __construct() {
add_action( 'init', array ( $this , 'action_init' ) );
// AJAX hooks here
}
Solution: Move the AJAX hook registration earlier in the load process:
add_action( 'plugins_loaded', array( $this, 'init' ) );
private function init() {
// Register AJAX hooks immediately
add_action('wp_ajax_add_row', array( $this, 'add_row' ));
add_action('wp_ajax_nopriv_add_row', array( $this, 'add_row' ));
}
Step-by-Step Troubleshooting
Step 1: Basic Verification
- Check browser network tab: Look at the actual request details in your browser’s developer tools
- Verify action parameter: Ensure
action: 'add_row'matches your registered hook exactly - Test with simplified request: Remove the nonce temporarily to isolate the issue
// Test without nonce
$.ajax({
url: tax_object.ajax_url,
type: 'post',
data: {
action: 'add_row'
},
success: function (response) {
console.log(response);
}
});
Step 2: Debug Server Response
Add debugging to your PHP handler:
public function add_row() {
// Log all received data
error_log("Received data: " . print_r($_REQUEST, true));
error_log("Action: " . $_REQUEST['action']);
// Return something to test
wp_send_json_success('Hello World');
}
Step 3: Check for Plugin Conflicts
As recommended in the research findings:
“Check if the issue persists when deactivating all plugins or switching to a default WordPress theme”
- Deactivate all plugins except yours
- Switch to a default theme (like Twenty Twenty-Four)
- Test the AJAX call
- If it works, re-enable plugins one by one to find the conflict
Step 4: Reset Permalinks
Corrupted permalink settings can cause 400 errors:
- Go to Settings > Permalinks
- Don’t make any changes, just click “Save Changes”
- Test your AJAX call again
Advanced CORS Configuration
If you’re making cross-origin requests, you’ll need to configure CORS headers:
Method 1: Using WordPress Filters
add_filter('allowed_http_origins', function($origins) {
// Add your domain
$origins[] = 'https://yourdomain.com';
return $origins;
});
add_filter('wp_headers', function($headers) {
$headers['Access-Control-Allow-Origin'] = 'https://yourdomain.com';
$headers['Access-Control-Allow-Credentials'] = 'true';
return $headers;
});
Method 2: Using .htaccess (for Apache)
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "https://yourdomain.com"
Header set Access-Control-Allow-Credentials "true"
</IfModule>
Method 3: Using PHP in theme functions
add_action('send_headers', function() {
header('Access-Control-Allow-Origin: https://yourdomain.com');
header('Access-Control-Allow-Credentials: true');
});
Plugin and Theme Conflicts
If the issue persists after basic troubleshooting:
- Check for JavaScript conflicts: Look for other scripts that might be interfering
- Verify nonce implementation: Ensure your nonce is properly created and verified
- Check server logs: Look for PHP errors or warnings
Alternative Approaches
1. Use WordPress REST API
Consider migrating to the modern WordPress REST API instead of the legacy admin-ajax.php:
fetch('/wp-json/wp/v2/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce
},
body: JSON.stringify({
title: 'Hello World'
})
})
2. Frontend-Only Solution
If your AJAX call doesn’t require WordPress backend processing, consider handling it entirely on the frontend:
// Process data without server roundtrip
function addRow() {
// Your frontend logic here
console.log('Row added');
}
3. Check Server Configuration
If you’re on a local development environment like MAMP, server configuration might be causing issues:
- Check PHP error logs
- Verify server modules are enabled
- Ensure proper file permissions
Remember that the “strict-origin-when-cross-origin” error is primarily a browser security feature, so focus first on ensuring your request format is correct before diving into CORS configuration. The 400 error suggests the server is rejecting your request before it can even process the CORS headers.
Sources
- Stack Overflow - Getting a 400 error with WordPress AJAX call
- WordPress Stack Exchange - Cannot load admin-ajax.php
- Expertrec - Troubleshooting Admin-ajax.php 400 Error
- WPBeginner - Fix WordPress Admin Ajax 400 Error
- WordPress Stack Exchange - admin-ajax.php 400 bad request
- 24x7 WP Support - Fix WordPress admin-ajax.php 400 Error
Conclusion
The WordPress AJAX 400 error with “strict-origin-when-cross-origin” typically stems from one of these issues:
- Incorrect action parameter leading to server rejection
- Content-Type mismatch between frontend and backend expectations
- CORS policy blocking cross-origin requests
- Plugin or theme conflicts interfering with AJAX execution
- Improper hook registration timing
Start with the simplest troubleshooting steps: verify your action parameter, remove any custom content-type settings, and test with a minimal request. If the issue persists, investigate plugin conflicts and CORS configuration. Consider migrating to the WordPress REST API for a more modern approach if you continue to face issues with the legacy admin-ajax.php endpoint.