<?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: Pshtiwan Mahmood</title>
    <description>The latest articles on DEV Community by Pshtiwan Mahmood (@kardoqadir).</description>
    <link>https://dev.to/kardoqadir</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F150646%2Fc8b84e20-13e5-4999-9bf9-51ba954169dd.jpg</url>
      <title>DEV Community: Pshtiwan Mahmood</title>
      <link>https://dev.to/kardoqadir</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kardoqadir"/>
    <language>en</language>
    <item>
      <title>The Hidden Trap of Dart Streams, Isolates, and ReceivePorts: Why Your Listeners Stop Working (and How to Fix It)</title>
      <dc:creator>Pshtiwan Mahmood</dc:creator>
      <pubDate>Sun, 14 Sep 2025 02:14:02 +0000</pubDate>
      <link>https://dev.to/kardoqadir/the-hidden-trap-of-dart-streams-isolates-and-receiveports-why-your-listeners-stop-working-and-504g</link>
      <guid>https://dev.to/kardoqadir/the-hidden-trap-of-dart-streams-isolates-and-receiveports-why-your-listeners-stop-working-and-504g</guid>
      <description>&lt;h1&gt;
  
  
  The Hidden Trap of Dart Streams, Isolates, and ReceivePorts: Why Your Listeners Stop Working (and How to Fix It)
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you use Dart isolates with &lt;code&gt;ReceivePort&lt;/code&gt; and expose its stream to your Flutter UI, your listeners will silently break whenever you restart the isolate. The fix? Use a persistent &lt;code&gt;StreamController.broadcast()&lt;/code&gt; as your public stream and pipe all events into it.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem: Listeners That Stop Listening
&lt;/h2&gt;

&lt;p&gt;Recently, I hit a frustrating bug in my Flutter app. I was using isolates to fetch real-time data, exposing a &lt;code&gt;dataStream&lt;/code&gt; getter in my service like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;dataStream&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="n"&gt;_receiver&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_receiver&lt;/span&gt;&lt;span class="o"&gt;!&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;In my UI, I’d listen to &lt;code&gt;dataStream&lt;/code&gt; in &lt;code&gt;initState()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;_realtimeInstance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dataStream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// update state&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It worked—until I restarted the service (by calling &lt;code&gt;start()&lt;/code&gt; again). Suddenly, my UI stopped receiving updates. No errors, no warnings, just… silence.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Subtle Cause: ReceivePort Replacement
&lt;/h2&gt;

&lt;p&gt;Every time you call &lt;code&gt;start()&lt;/code&gt;, you create a new &lt;code&gt;ReceivePort&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;_receiver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ReceivePort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But your UI is still listening to the old stream! The new &lt;code&gt;ReceivePort&lt;/code&gt; is a new stream object, and your listeners are now disconnected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Your UI never receives data after the first restart.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why Isn’t This in the Docs?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Dart/Flutter docs focus on simple, static streams.&lt;/li&gt;
&lt;li&gt;Most tutorials don’t cover isolates, or dynamic replacement of streams.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ReceivePort&lt;/code&gt; docs don’t warn you about this “hot swap” problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of those bugs you only learn about the hard way.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Robust Solution: Persistent StreamController
&lt;/h2&gt;

&lt;p&gt;Here’s the pattern you want:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create a private, persistent &lt;code&gt;StreamController.broadcast()&lt;/code&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expose its stream as your public API.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pipe all data from your &lt;code&gt;ReceivePort&lt;/code&gt; into this controller.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;StreamController&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StreamController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;broadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;dataStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;_receiver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ReceivePort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;_receiver&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// ... start isolate, etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, your UI can listen to &lt;code&gt;dataStream&lt;/code&gt; once, and always receive updates—no matter how many times you start/stop the service or replace the port.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Never expose a stream that may be replaced under the hood.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Always use a persistent &lt;code&gt;StreamController.broadcast()&lt;/code&gt; for your public API.&lt;/li&gt;
&lt;li&gt;Pipe all sources (ReceivePort, sockets, etc.) into it.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Bonus: Why Is This a “Broadcast” Stream?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A broadcast stream allows multiple listeners (e.g., UI, logs, analytics).&lt;/li&gt;
&lt;li&gt;It prevents “single subscription” errors if you have more than one consumer.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you’re building anything with Dart isolates and real-time data, this pattern will save you hours of silent bugs and confusion. I wish I’d seen this in the docs—so I’m writing it for you!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Did this save you? Let me know in the comments, or share your own Dart gotchas!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Dr. Pshtiwan Mahmood&lt;br&gt;&lt;br&gt;
Flutter/Dart Enthusiast | Real-time Systems Debugger&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>isolates</category>
      <category>streams</category>
    </item>
    <item>
      <title>Solving the Flutter `did_send` Crash: A Deep Dive into Isolate Race Conditions</title>
      <dc:creator>Pshtiwan Mahmood</dc:creator>
      <pubDate>Tue, 22 Jul 2025 17:44:43 +0000</pubDate>
      <link>https://dev.to/kardoqadir/solving-the-flutter-didsend-crash-a-deep-dive-into-isolate-race-conditions-415n</link>
      <guid>https://dev.to/kardoqadir/solving-the-flutter-didsend-crash-a-deep-dive-into-isolate-race-conditions-415n</guid>
      <description>&lt;h1&gt;
  
  
  Solving the Flutter &lt;code&gt;did_send&lt;/code&gt; Crash: A Deep Dive into Isolate Race Conditions
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: A race condition in Flutter isolate communication was causing fatal &lt;code&gt;did_send&lt;/code&gt; crashes in our production sports app. The fix required async coordination, proper cleanup sequencing, and a critical 100ms delay. Here's how we solved it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🚨 The Problem: A Production Nightmare
&lt;/h2&gt;

&lt;p&gt;Imagine this scenario: Your Flutter app is running smoothly in production with thousands of daily users. Everything works perfectly until users start reporting random crashes when navigating to specific screens. The crash logs show a cryptic, terrifying error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[FATAL:flutter/lib/ui/window/platform_message_response_dart_port.cc(53)] 
Check failed: did_send.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This wasn't just any crash—it was a &lt;strong&gt;fatal engine error&lt;/strong&gt; that would completely terminate the app. No graceful error handling, no recovery, no second chances. Just instant death. 💀&lt;/p&gt;

&lt;p&gt;The worst part? The error message gave us absolutely no context about what was causing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  📱 The App: Real-Time Sports Data at Scale
&lt;/h2&gt;

&lt;p&gt;Our app is a comprehensive sports statistics platform serving thousands of users. It provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚽ Live match scores updated every 5 seconds&lt;/li&gt;
&lt;li&gt;🏆 Real-time competition standings
&lt;/li&gt;
&lt;li&gt;📊 Player and team statistics&lt;/li&gt;
&lt;li&gt;🌍 Multi-language support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real-time functionality is the heart of our app, powered by &lt;strong&gt;Flutter isolates&lt;/strong&gt; that run background timers, fetch data from APIs, and stream updates to the main UI thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Two main services handling real-time data&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RealtimeDataService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handles general sports data (all games)&lt;/span&gt;
  &lt;span class="c1"&gt;// Updates every 5 seconds via isolate&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SingleRealtimeDataService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handles specific game data&lt;/span&gt;
  &lt;span class="c1"&gt;// Updates every 5 seconds via isolate&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔍 The Investigation: Following the Crash Trail
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Understanding the &lt;code&gt;did_send&lt;/code&gt; Error
&lt;/h3&gt;

&lt;p&gt;After diving deep into Flutter's source code, I discovered that the &lt;code&gt;did_send&lt;/code&gt; error occurs when:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An isolate tries to send a message through a &lt;code&gt;SendPort&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The receiving &lt;code&gt;ReceivePort&lt;/code&gt; has already been closed/disposed&lt;/li&gt;
&lt;li&gt;Flutter engine's safety check fails: &lt;code&gt;did_send = false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;💥 FATAL CRASH&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Reproducing the Issue
&lt;/h3&gt;

&lt;p&gt;The crash had a very specific pattern. It happened when users:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;📱 Opened a modal dialog&lt;/li&gt;
&lt;li&gt;👆 Clicked on a list item&lt;/li&gt;
&lt;li&gt;🧭 Navigated to a detail screen&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This navigation sequence triggered our router observer, which managed the real-time services based on the current route.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Finding the Smoking Gun 🔫
&lt;/h3&gt;

&lt;p&gt;Here's the problematic code that was causing our crashes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 🔴 PROBLEMATIC CODE (Before fix)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setRealtimeBaseOnRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Route&lt;/span&gt; &lt;span class="n"&gt;route&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="n"&gt;screen&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;TargetRoute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;singleRealtimeDataService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;     &lt;span class="c1"&gt;// Closes ReceivePort immediately&lt;/span&gt;
    &lt;span class="n"&gt;realtimeDataService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;           &lt;span class="c1"&gt;// Closes ReceivePort immediately  &lt;/span&gt;
    &lt;span class="n"&gt;realtimeDataService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;          &lt;span class="c1"&gt;// Starts new isolate immediately&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;&lt;strong&gt;The Race Condition Explained:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;stop()&lt;/code&gt; kills the isolate and closes &lt;code&gt;ReceivePort&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;start()&lt;/code&gt; creates a new isolate immediately&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;But the old isolate hadn't finished cleanup yet!&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Old isolate timer fires → tries to send to CLOSED port → &lt;strong&gt;CRASH&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ✅ The Solution: Proper Async Coordination
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fix #1: Make Operations Asynchronous
&lt;/h3&gt;

&lt;p&gt;The key insight was that isolate lifecycle management needed to be &lt;strong&gt;properly coordinated&lt;/strong&gt; with async/await:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ FIXED CODE (After solution)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setRealtimeBaseOnRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Route&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ScreenDetailData&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;route&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="n"&gt;screen&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;TargetRoute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Wait for complete cleanup before proceeding&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;singleRealtimeDataService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stop&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;realtimeDataService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;        

      &lt;span class="c1"&gt;// 🔧 CRITICAL: Wait for isolate cleanup&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delayed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;milliseconds:&lt;/span&gt; &lt;span class="mi"&gt;100&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;realtimeDataService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;shouldStart:&lt;/span&gt; &lt;span class="kc"&gt;true&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;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Error in route management: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Don't rethrow to prevent app crashes&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;h3&gt;
  
  
  Fix #2: Enhanced Service Architecture
&lt;/h3&gt;

&lt;p&gt;I also refactored the isolate services to be more robust:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RealtimeDataService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ReceivePort&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;_receiver&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Isolate&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;_isolate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;_isStarted&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="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;_isStarting&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;// 🔧 Prevents race conditions&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&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="n"&gt;_isStarted&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;_isStarting&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_isStarting&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;// Kill isolate first&lt;/span&gt;
      &lt;span class="n"&gt;_isolate&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;kill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;priority:&lt;/span&gt; &lt;span class="n"&gt;Isolate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;immediate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;_isolate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="c1"&gt;// Close receive port&lt;/span&gt;
      &lt;span class="n"&gt;_receiver&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;_receiver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="n"&gt;_isStarted&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;developer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Error stopping service: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;'&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="n"&gt;Stream&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;dataStream&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="n"&gt;_receiver&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_receiver&lt;/span&gt;&lt;span class="o"&gt;!&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fix #3: The Magic 100ms Delay ⏰
&lt;/h3&gt;

&lt;p&gt;You might wonder: &lt;em&gt;"Why 100ms? Isn't that arbitrary?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not at all! This delay is crucial because it gives the Flutter engine enough time to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Complete isolate termination&lt;/li&gt;
&lt;li&gt;✅ Close all message ports&lt;/li&gt;
&lt;li&gt;✅ Clean up platform channels&lt;/li&gt;
&lt;li&gt;✅ Ensure no orphaned messages&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 The Technical Deep Dive: Timeline Analysis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Before the Fix (Race Condition):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⏰ Time 0ms:   User navigates
⏰ Time 1ms:   Navigation starts
⏰ Time 2ms:   stop() called → ReceivePort closes
⏰ Time 3ms:   start() called → New ReceivePort opens
⏰ Time 4ms:   Old isolate timer fires → tries to send to CLOSED port
⏰ Time 5ms:   💥 CRASH: did_send check fails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  After the Fix (Proper Sequencing):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⏰ Time 0ms:   User navigates
⏰ Time 1ms:   Navigation starts
⏰ Time 2ms:   await stop() → ReceivePort closes + isolate cleanup
⏰ Time 50ms:  Old isolate fully terminated
⏰ Time 100ms: Safety delay complete
⏰ Time 101ms: await start() → New ReceivePort opens
⏰ Time 102ms: ✅ SUCCESS: Clean transition
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📚 Lessons Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. 🔗 Isolate Communication is Fragile
&lt;/h3&gt;

&lt;p&gt;Platform message channels in Flutter are low-level and unforgiving. Always ensure proper cleanup sequencing.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. ⚡ Async/Await Saves Lives
&lt;/h3&gt;

&lt;p&gt;What seemed like a simple synchronous operation actually required careful async coordination.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 🕵️ Production Errors Need Deep Investigation
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;did_send&lt;/code&gt; error gave no context about the root cause. Only systematic investigation revealed the race condition.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. 🛡️ Error Handling is Critical
&lt;/h3&gt;

&lt;p&gt;Always wrap isolate operations in try-catch blocks to prevent crashes from propagating.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎉 The Results
&lt;/h2&gt;

&lt;p&gt;After implementing these fixes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Zero crashes&lt;/strong&gt; related to the &lt;code&gt;did_send&lt;/code&gt; error&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Smooth navigation&lt;/strong&gt; between all screens&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Robust error handling&lt;/strong&gt; prevents future isolate issues&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Production stability&lt;/strong&gt; with thousands of daily users&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Key Takeaways for Flutter Developers
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Always use async/await&lt;/strong&gt; when managing isolate lifecycles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add delays between stop/start operations&lt;/strong&gt; to ensure cleanup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement comprehensive error handling&lt;/strong&gt; for isolate operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test navigation flows thoroughly&lt;/strong&gt; in production-like conditions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor crash logs&lt;/strong&gt; for platform-level errors&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  💭 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Debugging production crashes can be incredibly challenging, especially when the error messages are cryptic. This experience taught me the importance of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Systematic investigation&lt;/strong&gt; over quick fixes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understanding the underlying platform&lt;/strong&gt; (Flutter engine internals)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proper async coordination&lt;/strong&gt; in complex systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comprehensive error handling&lt;/strong&gt; to prevent cascading failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;did_send&lt;/code&gt; crash was a reminder that even small race conditions can have catastrophic effects in production. But with the right approach, even the most mysterious bugs can be solved.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 Discussion
&lt;/h2&gt;

&lt;p&gt;Have you encountered similar isolate issues in your Flutter apps? What debugging strategies worked for you? Share your experiences in the comments below!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What would you like to see next?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More Flutter debugging deep dives?&lt;/li&gt;
&lt;li&gt;Performance optimization techniques?&lt;/li&gt;
&lt;li&gt;Real-time app architecture patterns?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me know! 👇&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If this helped you solve a similar issue, please give it a ❤️ and share it with your fellow Flutter developers!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>isolates</category>
      <category>debugging</category>
    </item>
  </channel>
</rss>
