<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Axis Web Art</title>
    <description>The latest articles on DEV Community by Axis Web Art (@axiswebart).</description>
    <link>https://dev.to/axiswebart</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F255381%2Febdbea84-c6fb-4f7c-b153-35c638a23ef9.jpg</url>
      <title>DEV Community: Axis Web Art</title>
      <link>https://dev.to/axiswebart</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/axiswebart"/>
    <language>en</language>
    <item>
      <title>A race condition in WordPress's page lifecycle was injecting "404" into my login page</title>
      <dc:creator>Axis Web Art</dc:creator>
      <pubDate>Mon, 29 Jun 2026 13:41:53 +0000</pubDate>
      <link>https://dev.to/axiswebart/a-race-condition-in-wordpresss-page-lifecycle-was-injecting-404-into-my-login-page-31d5</link>
      <guid>https://dev.to/axiswebart/a-race-condition-in-wordpresss-page-lifecycle-was-injecting-404-into-my-login-page-31d5</guid>
      <description>&lt;p&gt;I run a white label web agency. Every client site ends with the same setup: custom login page, branded emails, WordPress fingerprint removed. After doing it manually on dozens of sites I built a plugin to automate it. Then a client sent me a screenshot of a "404" error showing in a red box on the login page on a page that was loading fine.&lt;/p&gt;

&lt;p&gt;This is what I found.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;The plugin moves &lt;code&gt;/wp-login.php&lt;/code&gt; to a custom slug — say &lt;code&gt;/client-portal/&lt;/code&gt;. Direct requests to the old URL redirect home. The custom URL serves the real login page via &lt;code&gt;template_redirect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That part worked fine. But on the live site with Rank Math SEO installed, a "404" string was appearing in the login form's error output on every fresh page load — before any login attempt was made.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was actually happening
&lt;/h2&gt;

&lt;p&gt;WordPress runs its main query before &lt;code&gt;template_redirect&lt;/code&gt; fires. The execution order inside &lt;code&gt;WP::main()&lt;/code&gt; is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;init&lt;/code&gt; hooks&lt;/li&gt;
&lt;li&gt;&lt;code&gt;parse_request()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;query_posts()&lt;/code&gt; ← the main query runs here&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;handle_404()&lt;/code&gt; ← 404 detection here&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wp&lt;/code&gt; action&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;template_redirect&lt;/code&gt; ← where we serve the login page&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the custom slug &lt;code&gt;/client-portal/&lt;/code&gt;, the main query at step 3 finds no matching post or page. So it sets &lt;code&gt;$wp_query-&amp;gt;is_404 = true&lt;/code&gt;. By the time we intercept the request in step 6 and serve &lt;code&gt;wp-login.php&lt;/code&gt;, that flag has been set for three steps.&lt;/p&gt;

&lt;p&gt;Rank Math hooks into WordPress's &lt;code&gt;login_errors&lt;/code&gt; filter and checks &lt;code&gt;is_404()&lt;/code&gt;. If it returns &lt;code&gt;true&lt;/code&gt;, Rank Math injects "404" as an error string. WordPress passes it straight through to the login form output— no authentication attempt needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;WordPress has a &lt;code&gt;pre_handle_404&lt;/code&gt; filter that fires inside &lt;code&gt;handle_404()&lt;/code&gt; at step 4. Returning &lt;code&gt;true&lt;/code&gt; from it prevents the 404 status header from being sent. But — and this is the part that took me a while — it does &lt;strong&gt;not&lt;/strong&gt; reset &lt;code&gt;$wp_query-&amp;gt;is_404&lt;/code&gt;. That property is set in &lt;code&gt;query_posts()&lt;/code&gt; at step 3, and nothing in &lt;code&gt;handle_404()&lt;/code&gt; clears it. The filter only stops the header.&lt;/p&gt;

&lt;p&gt;You have to reset it explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt;
&lt;span class="nf"&gt;add_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'pre_handle_404'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'prevent_404'&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;prevent_404&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nv"&gt;$handled&lt;/span&gt; &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="nv"&gt;$wp_query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_request_path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_slug&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$wp_query&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="n"&gt;WP_Query&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$wp_query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;is_404&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// must be cleared explicitly&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// prevents 404 status header&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$handled&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, is_404() returns false when login_errors fires. Rank Math&lt;br&gt;
finds nothing to inject. The error box disappears.&lt;/p&gt;

&lt;p&gt;The instanceof WP_Query guard matters — on certain admin and AJAX requests the global may not be initialised, and a typed parameter hint on the method would cause a fatal in those cases.&lt;/p&gt;

&lt;p&gt;The interim-login popup problem WordPress has a heartbeat-based session check that shows a small popup when your admin session expires. It loads the login page in an iframe at roughly 400×500px and adds body.interim-login to the page body.&lt;/p&gt;

&lt;p&gt;Every template in the plugin used full-page layout assumptions —&lt;br&gt;
min-height: 100vh, flexbox stretch, fixed-position side panels. In a 400px iframe the username field was above the visible area with no scroll. Unusable.&lt;/p&gt;

&lt;p&gt;The CSS fix scopes overrides to body.interim-login:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="nc"&gt;.interim-login.als-login&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--als-form-bg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Hide fixed panels that only make sense full-page */&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="nc"&gt;.interim-login.als-login.template-split&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="nc"&gt;.interim-login.als-login.template-fullscreen&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the support footer that was overflowing the popup bottom, CSS wasn't reliable enough whether body.interim-login is added varies slightly between WordPress versions. A server-side check is unconditional:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;footer_content&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$_REQUEST&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'interim-login'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// render footer...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;pre_handle_404&lt;/code&gt; filter is documented as "fires before WordPress handles the 404" — which is accurate but incomplete. It fires before the response is handled. The query result that triggered the 404 detection is already set and stays set unless you clear it yourself.&lt;/p&gt;

&lt;p&gt;If you're serving custom pages from template_redirect on URLs that don't match real posts, check whether any installed plugins read &lt;code&gt;is_404()&lt;/code&gt; downstream. The &lt;code&gt;pre_handle_404&lt;/code&gt; filter is the right hook — just remember to reset the property, not only return true.&lt;/p&gt;

&lt;p&gt;The plugin is free and open source if you want to look at the full&lt;br&gt;
implementation: &lt;a href="https://github.com/Axis-Web-Art/agency-login-suite" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;br&gt;
· &lt;a href="https://wordpress.org/plugins/axiswebart-agency-login-suite/" rel="noopener noreferrer"&gt;WordPress.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I do &lt;a href="https://www.axiswebart.com/white-label-wordpress-development/" rel="noopener noreferrer"&gt;white label WordPress development for agencies&lt;/a&gt; and this came out of real client work, most of the interesting bugs do.&lt;/p&gt;

&lt;p&gt;Written with AI assistance #ABotWroteThis&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Delhivery LastMile – Magento 2 Integration</title>
      <dc:creator>Axis Web Art</dc:creator>
      <pubDate>Thu, 24 Oct 2019 07:19:39 +0000</pubDate>
      <link>https://dev.to/axiswebart/delhivery-lastmile-magento-2-integration-431f</link>
      <guid>https://dev.to/axiswebart/delhivery-lastmile-magento-2-integration-431f</guid>
      <description>&lt;p&gt;This is the official extension by Delhivery to support the integration of our Delhivery Lastmile service with Magento 2. The extension works in Magento 2 Backend and allows merchants to -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ship Orders via Delhivery last mile&lt;/li&gt;
&lt;li&gt;Assign tracking numbers to order&lt;/li&gt;
&lt;li&gt;Submit Manifest&lt;/li&gt;
&lt;li&gt;Download &amp;amp; Print Packaging Slip&lt;/li&gt;
&lt;li&gt;Create a Pickup Request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The extension is developed by Axis Web Art, a Jaipur &amp;amp; Gurgaon based &lt;a href="https://www.axiswebart.com/" rel="noopener noreferrer"&gt;web development company in India&lt;/a&gt;. Contact Axis Web Art for any help required with installation &amp;amp; extension usages related problems.&lt;/p&gt;

&lt;p&gt;Purpose:&lt;/p&gt;

&lt;p&gt;The purpose of this plug-in is to integrate Delhivery LastMile processes with eCommerce stores running on Magento 2. It provides the following features - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download and Store client-specific AWB series from the Delhivery system.&lt;/li&gt;
&lt;li&gt;Download and Store a list of serviceable Pin Code from the Delhivery system.&lt;/li&gt;
&lt;li&gt;Allocate AWB to Order automatically from the stored list while shipping order and Delhivery selected as Carrier&lt;/li&gt;
&lt;li&gt;Pin code Check while shipping order.&lt;/li&gt;
&lt;li&gt;The facility to submit manifest for the allocated AWB.&lt;/li&gt;
&lt;li&gt;Facility to print shipping labels for the selected AWB.&lt;/li&gt;
&lt;li&gt;Facility to create request pickup &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Complete installation and Usages guide is available here - &lt;br&gt;
&lt;a href="https://docs.google.com/document/d/1XjqHlEt4imlQkp9RunUtdSgowi2rD_XHxu3NFkgkgpw/edit?usp=sharing" rel="noopener noreferrer"&gt;https://docs.google.com/document/d/1XjqHlEt4imlQkp9RunUtdSgowi2rD_XHxu3NFkgkgpw/edit?usp=sharing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Download Extension Package for your version of Magento 2 from the drive link below - &lt;br&gt;
&lt;a href="https://drive.google.com/open?id=1EnC8PtWYdMT8L3F8HgrddKT9gNcoNlxQ" rel="noopener noreferrer"&gt;https://drive.google.com/open?id=1EnC8PtWYdMT8L3F8HgrddKT9gNcoNlxQ&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contact your &lt;a href="https://www.delhivery.com/" rel="noopener noreferrer"&gt;Delhivery&lt;/a&gt; account manager for the required API credentials.&lt;br&gt;&lt;br&gt;
Contact &lt;a href="https://www.axiswebart.com/" rel="noopener noreferrer"&gt;Axis Web Art&lt;/a&gt; for installation and extension support.&lt;/p&gt;

</description>
      <category>delhiverymagento</category>
      <category>magentodelhivery</category>
    </item>
  </channel>
</rss>
