Troubleshooting guide · wordpress · Published 2026-08-16 · 3 min read
A WordPress REST route conflict explained
WordPress REST API route conflict: duplicate namespaces or routes, how to spot them, and how to fix conflicting endpoint registration.
- ·Symptoms
- ·How a conflict happens
- ·Fix and prevent
Symptoms
WordPress exposes data over the REST API, and the REST API basics article explains how routes and namespaces work. A route conflict shows up as REST endpoints behaving wrongly without any PHP warning on the page:
- A
/wp-json/endpoint returns arest_no_routeerror even though you know a plugin registers it. - The endpoint returns the wrong data, from a different plugin than the one you configured.
- Only one of two plugins that should expose the same API works at a time, and it flips when you deactivate one of them.
The key clue: the fault appears only on REST routes, not on the front end, and it moves when you toggle the two plugins that share a namespace.
How a conflict happens
A REST route has two parts, a namespace and an individual route. When two plugins call register_rest_route() with the exact same combination, only one registration wins, WordPress keeps whichever came last, and the other plugin gets a silent rest_no_route for its calls.
Two registration calls that collide:
register_rest_route( 'my-plugin/v1', '/settings', array(
'methods' => 'GET',
'callback' => 'my_plugin_get_settings',
) );
register_rest_route( 'my-plugin/v1', '/settings', array(
'methods' => 'GET',
'callback' => 'other_plugin_get_settings',
) );
Both register my-plugin/v1/settings. WordPress does not reject the second one at compile time, it simply overwrites or ignores one, so the callback that answers is whichever registered last, and the other plugin's /settings silently disappears. Namespace collisions are the most common form because v1 or the plugin title is a popular namespace choice.
Fix and prevent
The fix is to give each plugin a unique namespace and route so no two registrations collide:
- Find the two colliding callbacks. Deactivate plugins in halves, following the plugin conflict ladder, until one toggle changes the route's behaviour.
- Identify the namespace. The easiest is to add
WP_DEBUGandWP_DEBUG_LOGtowp-config.php, request the colliding/wp-json/...URL, and read which plugin produced therest_no_routeinwp-content/debug.log. - De-duplicate the namespace or route. The plugin that owns the endpoint should register a unique namespace, for example
my-plugin/v2, instead of sharingmy-plugin/v1/settings. If a third-party theme or plugin is the offender and you cannot edit it cleanly, prefer replacing it with an equivalent that namespaced correctly. - Flush the permalinks once you change namespaces. Visit Settings, Permalinks, and Save, or use the WP-CLI rest route list alongside a
wp rewrite flushto make the new routes registrable. - Test the endpoint. Re-request
/wp-json/and confirm the correct callback now answers and the other plugin's route responds without arest_no_route.
Prevent the class entirely by convention: every plugin your team writes should use a unique vendor prefix in its namespace, vendor-name/plugin-name/v1, never a bare v1 or a generic word, and it should be mindful that a plugin can break an API silently when it reuses another plugin's namespace. A cheap habit, a unique namespace, avoids a whole class of conflicts that are otherwise hard to see because the failure lives only in the REST layer.