Troubleshooting
Common issues and fixes for WPZylos Routing.
Frontend Routes
Routes Not Working
Symptom: Custom URLs return 404 errors.
Causes & Fixes:
- Rewrite rules not flushed
// Flush on plugin activation register_activation_hook(__FILE__, function () { WPAdapter::flush(); }); - Permalinks not enabled
- Go to Settings → Permalinks
- Select any option except "Plain"
- Save changes
- Route registered after
inithook- Ensure service provider boots early
Route Parameters Empty
Symptom: $id is empty in handler fn($id) => ...
Fix: Ensure route pattern uses correct syntax:
// Correct
$router->get('/users/{id}', fn($id) => "User: {$id}");
// Wrong
$router->get('/users/:id', fn($id) => "User: {$id}");
REST API
Endpoint Returns 404
Symptom: /wp-json/my-plugin/v1/endpoint returns 404.
Causes:
- REST API not initialized
// Ensure routes are registered on rest_api_init add_action('rest_api_init', function () { // Routes should auto-register via service provider }); - Wrong namespace
// Check your namespace matches $rest = new RestRouter($context, $container); // Namespace: {slug}/v1 - Pretty permalinks disabled
- REST API requires non-plain permalinks
Permission Denied (403)
Symptom: All authenticated requests return 403.
Fixes:
- Check capability exists
// Verify capability current_user_can('your_capability'); - Check permission callback return type
// Must return boolean, not WP_Error ->setPermissionCallback(fn() => current_user_can('edit_posts'))
Request Parameters Empty
Symptom: $request->get_param('key') returns null.
Fixes:
- Check Content-Type header
fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ key: "value" }), }); - For form data, use FormData
const formData = new FormData(); formData.append("key", "value"); fetch(url, { method: "POST", body: formData });
AJAX
Invalid Nonce Error
Symptom: "Invalid nonce" error on AJAX requests.
Fixes:
- Nonce not passed
data: { action: 'myplugin_save', _wpnonce: myPluginData.nonce, // Add this ... } - Wrong nonce action
// Nonce action must match $ajax->nonce('save_settings'); // Generate $ajax->private('save_settings', [...]); // Route // Action: myplugin_save_settings - Nonce expired
- Nonces expire after 24 hours
- Regenerate on page load
Action Not Found
Symptom: "0" or empty response.
Fixes:
- Wrong action name
// Include plugin prefix action: "myplugin_action_name"; // Not 'action_name' - Route not registered
- Check that route file is loaded
- Verify service provider is registered
JSON Parse Error
Symptom: SyntaxError: Unexpected token in JavaScript.
Causes:
- PHP errors in response
- Check for PHP notices/warnings
- Enable WP_DEBUG_LOG and check logs
- Response not JSON
- Ensure controller returns array
- Don't echo/print in handlers
Middleware
Middleware Not Running
Symptom: Middleware handle() never called.
Fixes:
- Middleware not registered in container
$container->singleton(AuthMiddleware::class); - Wrong middleware class name
// Use fully qualified class name ->middleware(App\Middleware\AuthMiddleware::class)
Middleware Order Wrong
Symptom: Middleware runs in unexpected order.
Note: Middleware runs in the order specified:
->middleware([First::class, Second::class, Third::class])
// Order: First → Second → Third → Handler → Third → Second → First
Common Errors
"Class not found" on Route Handler
Fix: Ensure autoloading is configured:
// composer.json
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Run composer dump-autoload.
"Cannot use object of type Closure"
Fix: Wrap closures properly:
// Correct
$router->get('/test', fn() => ['data' => 'value']);
// Wrong
$router->get('/test', ['data' => 'value']); // Not a handler
"Undefined property: $route"
Fix: Return value from middleware:
public function handle($request, callable $next): mixed
{
// Must call and return $next()
return $next($request); // Don't forget this!
}
Debug Mode
Enable WordPress debug mode for detailed errors:
// wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Check wp-content/debug.log for errors.