<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Syed Zubyl N | Software Developer - Debugging</title>
      <link>https://syedzubyl.space</link>
      <description>Syed Zubyl N — Software Developer focused on Java, Spring Boot, backend development, REST APIs, databases, Flutter and production-oriented applications.</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://syedzubyl.space/tags/debugging/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sat, 14 Feb 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Debugging a 405 Method Not Allowed Error in a Mobile API</title>
          <pubDate>Sat, 14 Feb 2026 00:00:00 +0000</pubDate>
          <author>Syed Zubyl N</author>
          <link>https://syedzubyl.space/blog/debugging-405-error/</link>
          <guid>https://syedzubyl.space/blog/debugging-405-error/</guid>
          <description xml:base="https://syedzubyl.space/blog/debugging-405-error/">&lt;h3 id=&quot;the-problem&quot;&gt;The Problem&lt;&#x2F;h3&gt;
&lt;p&gt;While developing a mobile application, a specific API endpoint for fetching user profile data suddenly started failing. The mobile client was receiving a &lt;code&gt;405 Method Not Allowed&lt;&#x2F;code&gt; HTTP status code, and the data refused to load.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;context&quot;&gt;Context&lt;&#x2F;h3&gt;
&lt;p&gt;The application relies on a Spring Boot backend exposing RESTful endpoints. The mobile client (built in Flutter) communicates with this API using the &lt;code&gt;http&lt;&#x2F;code&gt; package. The endpoint in question was &lt;code&gt;&#x2F;api&#x2F;v1&#x2F;users&#x2F;profile&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-i-tried&quot;&gt;What I Tried&lt;&#x2F;h3&gt;
&lt;p&gt;At first, I assumed the authentication token was invalid or the endpoint URL was misspelled.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I checked the JWT token — it was valid.&lt;&#x2F;li&gt;
&lt;li&gt;I verified the URL string in the Dart code — it perfectly matched the backend controller.&lt;&#x2F;li&gt;
&lt;li&gt;I checked the server logs, expecting to see a &lt;code&gt;NullPointerException&lt;&#x2F;code&gt; or a &lt;code&gt;400 Bad Request&lt;&#x2F;code&gt;. Instead, Spring Security was just quietly rejecting the request at the filter level.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;what-failed&quot;&gt;What Failed&lt;&#x2F;h3&gt;
&lt;p&gt;I spent an hour looking at the backend logic, assuming the database query was failing or the routing was broken. None of this was the issue because the request wasn’t even reaching my controller method.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-worked-technical-explanation&quot;&gt;What Worked &amp;amp; Technical Explanation&lt;&#x2F;h3&gt;
&lt;p&gt;The breakthrough came when I bypassed the mobile app entirely and used Postman to test the endpoint.&lt;&#x2F;p&gt;
&lt;p&gt;When I sent a &lt;code&gt;GET&lt;&#x2F;code&gt; request in Postman: &lt;strong&gt;200 OK.&lt;&#x2F;strong&gt;
When I looked closely at my Flutter network layer:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #E1E4E8; background-color: #24292E;&quot;&gt;&lt;code data-lang=&quot;dart&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; The bug&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97583;&quot;&gt;final&lt;&#x2F;span&gt;&lt;span&gt; response &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97583;&quot;&gt;= await&lt;&#x2F;span&gt;&lt;span&gt; http.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B392F0;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #79B8FF;&quot;&gt;  Uri&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B392F0;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9ECBFF;&quot;&gt;&amp;#39;https:&#x2F;&#x2F;api.example.com&#x2F;api&#x2F;v1&#x2F;users&#x2F;profile&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  headers&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97583;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9ECBFF;&quot;&gt;&amp;#39;Authorization&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97583;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9ECBFF;&quot;&gt; &amp;#39;Bearer $&lt;&#x2F;span&gt;&lt;span style=&quot;color: #79B8FF;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9ECBFF;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The issue was glaringly simple: I was using &lt;code&gt;http.post&lt;&#x2F;code&gt; for an endpoint that the backend explicitly defined as a &lt;code&gt;@GetMapping&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;code&gt;405 Method Not Allowed&lt;&#x2F;code&gt; means exactly what it says: the server exists, the route exists, but the HTTP verb (GET, POST, PUT, DELETE) you used is not supported for that specific route. It is fundamentally different from a &lt;code&gt;404 Not Found&lt;&#x2F;code&gt; (route doesn’t exist) or a &lt;code&gt;400 Bad Request&lt;&#x2F;code&gt; (payload is wrong).&lt;&#x2F;p&gt;
&lt;p&gt;I corrected the mobile client to use &lt;code&gt;http.get&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #E1E4E8; background-color: #24292E;&quot;&gt;&lt;code data-lang=&quot;dart&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; The fix&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F97583;&quot;&gt;final&lt;&#x2F;span&gt;&lt;span&gt; response &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97583;&quot;&gt;= await&lt;&#x2F;span&gt;&lt;span&gt; http.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B392F0;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #79B8FF;&quot;&gt;  Uri&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #B392F0;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9ECBFF;&quot;&gt;&amp;#39;https:&#x2F;&#x2F;api.example.com&#x2F;api&#x2F;v1&#x2F;users&#x2F;profile&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  headers&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97583;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9ECBFF;&quot;&gt;&amp;#39;Authorization&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F97583;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9ECBFF;&quot;&gt; &amp;#39;Bearer $&lt;&#x2F;span&gt;&lt;span style=&quot;color: #79B8FF;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9ECBFF;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;lessons-learned&quot;&gt;Lessons Learned&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Read the HTTP Status Code literally.&lt;&#x2F;strong&gt; Don’t assume a 405 is a generic crash. It has a highly specific meaning defined by the HTTP protocol.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Isolate the client from the server.&lt;&#x2F;strong&gt; When an API fails in a mobile app, test the exact same request in &lt;code&gt;curl&lt;&#x2F;code&gt; or Postman immediately. This tells you instantly if the bug is in the client code (Flutter) or the server code (Spring Boot).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;what-i-would-do-differently&quot;&gt;What I Would Do Differently&lt;&#x2F;h3&gt;
&lt;p&gt;I will implement a centralized API client class in Flutter with strict typed methods (&lt;code&gt;fetchProfile()&lt;&#x2F;code&gt;, &lt;code&gt;updateProfile()&lt;&#x2F;code&gt;) rather than writing raw &lt;code&gt;http.get&lt;&#x2F;code&gt; or &lt;code&gt;http.post&lt;&#x2F;code&gt; calls scattered throughout the UI code. This reduces the surface area for simple typo bugs like using the wrong HTTP verb.&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
