<?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: Deepanshu Kumar</title>
    <description>The latest articles on DEV Community by Deepanshu Kumar (@dev-deepanshu-kumar).</description>
    <link>https://dev.to/dev-deepanshu-kumar</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%2F2071142%2Fb180a611-a0e2-4197-ad6b-59587b2291f8.png</url>
      <title>DEV Community: Deepanshu Kumar</title>
      <link>https://dev.to/dev-deepanshu-kumar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dev-deepanshu-kumar"/>
    <language>en</language>
    <item>
      <title>Why the Same Bug Keeps Coming Back - And How to Stop It</title>
      <dc:creator>Deepanshu Kumar</dc:creator>
      <pubDate>Tue, 21 Jul 2026 10:31:41 +0000</pubDate>
      <link>https://dev.to/dev-deepanshu-kumar/why-the-same-bug-keeps-coming-back-and-how-to-stop-it-4hd4</link>
      <guid>https://dev.to/dev-deepanshu-kumar/why-the-same-bug-keeps-coming-back-and-how-to-stop-it-4hd4</guid>
      <description>&lt;p&gt;A few months ago, I fixed a bug on a Friday afternoon. Status filter on a dashboard widget was returning empty results for some users. Found the problem, added one line, tests passed, shipped it. Felt good about it.&lt;/p&gt;

&lt;p&gt;The following Tuesday, someone filed another ticket. Different widget, same symptom. I looked at the code and felt that specific kind of embarrassment you get when you realize the answer was right in front of you the whole time.&lt;/p&gt;

&lt;p&gt;I hadn't fixed the bug. I fixed one place where the bug lived. The same broken pattern was sitting in three other handlers, and I hadn't thought to check.&lt;/p&gt;




&lt;h2&gt;
  
  
  What actually happened
&lt;/h2&gt;

&lt;p&gt;The app was a multi-tenant SaaS where users have permissions scoped to specific warehouses. Dashboard widgets query orders, but only the ones the user is allowed to see. Simple enough.&lt;/p&gt;

&lt;p&gt;We had six of these query handlers. Someone had written the first one correctly, copy-pasted it five times as new widgets were added, and somewhere along the way one important line kept getting dropped.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Priority widget handler — written correctly&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Priority&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetPrioritiesQuery&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;permittedWarehouses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_warehouseService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetPermittedWarehouseIds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;permittedWarehouses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// include orders with no warehouse assigned&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetPriorities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;permittedWarehouses&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Status widget handler — the one that broke&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetStatusesQuery&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;permittedWarehouses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_warehouseService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetPermittedWarehouseIds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// that null append never made it here&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetStatuses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;permittedWarehouses&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;The &lt;code&gt;null&lt;/code&gt; append matters because some orders aren't assigned to any warehouse. Without it, those orders get filtered out entirely. For users whose entire order history happened to be unassigned, the widget showed nothing at all.&lt;/p&gt;

&lt;p&gt;One line. Easy fix. But I only fixed it in the one handler that had broken visibly.&lt;/p&gt;

&lt;p&gt;When I finally audited all six:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GetOrderStatuses     → ❌ missing null append
GetOrderPriorities   → ✅ has null append  
GetOrderAssignees    → ❌ missing null append
GetOrderLocations    → ✅ has null append
GetOrderCategories   → ❌ missing null append
GetOrderCosts        → ✅ has null append
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three broken, three fine. The broken ones just hadn't surfaced yet, either because fewer users hit those widgets or because the affected users had quietly assumed the data wasn't there and moved on without filing a ticket.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this keeps happening
&lt;/h2&gt;

&lt;p&gt;The code didn't start inconsistent. Someone wrote the first handler carefully. The inconsistency crept in through copy-paste, through deadline pressure, through the very reasonable assumption that "this is basically the same as that other handler." Nobody set out to leave three bugs behind.&lt;/p&gt;

&lt;p&gt;The real trap is how bugs announce themselves. They don't show up as patterns. They show up as individual tickets, individual screens, individual complaints. Your natural instinct is to find the broken thing and fix it. That instinct is mostly right, but it misses a step: asking whether the broken thing is one instance of a broader pattern, or the pattern itself.&lt;/p&gt;

&lt;p&gt;In my case the pattern was "handlers that filter by warehouse permission don't consistently handle unassigned orders." I fixed one handler. I should have fixed the category.&lt;/p&gt;




&lt;h2&gt;
  
  
  The habit that changes this
&lt;/h2&gt;

&lt;p&gt;Before writing the fix, write down what's wrong in plain language. Not which file, not which method. The actual rule that got violated.&lt;/p&gt;

&lt;p&gt;Weak: "GetOrderStatuses doesn't append null to the warehouse list"&lt;/p&gt;

&lt;p&gt;Better: "Warehouse-permission queries don't consistently include null to catch unassigned orders"&lt;/p&gt;

&lt;p&gt;The second version is searchable. It tells you what to look for everywhere else, not just in the file you already have open.&lt;/p&gt;

&lt;p&gt;Then before merging, run the search:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"GetPermittedWarehouseIds"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"*.cs"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read every result. For each one ask: should this also have the fix? If yes, add it to the same PR. Not a follow-up ticket, not a "I'll get to it," the same PR.&lt;/p&gt;

&lt;p&gt;I know that feels like scope creep. It isn't. The one-line fix takes five minutes. The audit takes twenty. Skipping the audit trades twenty minutes now for two more Tuesday tickets later.&lt;/p&gt;




&lt;h2&gt;
  
  
  A way to think about it
&lt;/h2&gt;

&lt;p&gt;Imagine a building with fire suppression systems. You find one blocked sprinkler head. The right move is not to unblock it and sign off on the inspection. You check every head on that floor, because blocked sprinklers don't usually happen in isolation.&lt;/p&gt;

&lt;p&gt;The fix you wrote is the unblocked head. The audit is the inspection. Both are part of the job, and most engineers are very good at the first one and inconsistent about the second.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before you close the PR
&lt;/h2&gt;

&lt;p&gt;Three questions, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is the pattern in plain English? Not the file or method name, the rule that was broken.&lt;/li&gt;
&lt;li&gt;Where else does this pattern appear? Search for it. Do not assume you already know.&lt;/li&gt;
&lt;li&gt;Are all of those places now consistent? Fix them in this PR or file the follow-up tickets before the browser tab closes, while the context is still fresh.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The third question is the one that gets skipped. It got skipped by me on that Friday, and it cost a Tuesday.&lt;/p&gt;




&lt;p&gt;Bugs are rarely one-offs. The one that got reported was just the one someone noticed. The rest are waiting for the right user, the right data, the right edge case to make them visible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix the pattern. Not just the line.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Until next time,&lt;br&gt;
&lt;strong&gt;Deepanshu&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Backend engineer writing about production bugs, distributed systems, and engineering patterns learned the hard way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deepanshu-kumar.dev" rel="noopener noreferrer"&gt;Portfolio&lt;/a&gt; · &lt;a href="https://medium.com/@dev-deepanshu-kumar" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; · &lt;a href="https://www.linkedin.com/in/deepanshu-kumar-dev/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="https://github.com/Dev-Deepanshu-Kumar" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>softwareengineering</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
