“flutter run” starts the app but no logs / hot reload / debug output anymore

Summary

An Honor device connected via USB debugging suddenly stopped providing log output and hot reload functionality after a successful flutter run. The Gradle build and APK installation completed, but the observatory/VM service connection failed to establish silently. This broke log streaming, stdin command processing (hot reload/restart), and debugging. The root cause was likely a USB cable/port issue or an Android OS-level security/prompt that blocked the Dart VM binding, not a code or project configuration error.

Root Cause

  • Failed VM Service Handshake: The Flutter tool relies on the device notifying the host machine when the Dart VM starts and on which port (typically ephemeral, e.g., 127.0.0.1:54321). This is done via JDWP (Java Debug Wire Protocol) port forwarding. When this notification is missed or blocked, flutter thinks the app is running but disconnected.
  • ADB Connection Instability: The physical connection between the PC and the Honor phone became unstable. While adb install succeeded (pushing the file), the continuous adb logcat stream required for live logs and the adb reverse/forwarding required for hot reload dropped packets or timed out.
  • Android 11+ “Wireless Debugging” Interference: If “Wireless Debugging” was toggled on the Honor phone, it can conflict with standard USB debugging, hijacking the connection port or requiring a new pairing code that flutter cannot prompt for automatically.
  • Aggressive Battery Optimization/OS Kill: Honor/Huawei devices have aggressive power management (PowerGenie). If the OS detected the debug bridge as “heavy” or “background,” it might have suspended the process communication without killing the app UI itself.

Why This Happens in Real Systems

  • Ephemeral Ports: Flutter uses dynamic ports for the VM service. If the port mapping in adb drops, the tools cannot find where to send commands like “reload.”
  • ADB Transport Layer: ADB is not a robust network protocol; it’s a multiplexing stream over USB. High I/O load (during assembleDebug) or loose USB contacts can desynchronize the stream state, causing a “zombie” session where the install finishes but the shell listener dies.
  • OEM Android Skins: Manufacturers like Honor often modify the Android framework to aggressively kill background processes or restrict debugging interfaces to save battery, which violates standard Android behavior expected by flutter run.

Real-World Impact

  • Zero Observability: Developers cannot see print() statements, debugPrint(), or stack traces. This renders debugging effectively impossible.
  • Broken Developer Workflow: The standard cycle of Code -> Save -> Hot Reload -> Verify is broken. The developer must manually uninstall/reinstall the app on every change, increasing cycle time from seconds to minutes.
  • False Positives: The build success message (✓ Built...) makes it look like the tool worked, leading to confusion about why the code isn’t reflecting changes.

Example or Code

No code fixes this specific issue, but flutter doctor -v is the diagnostic tool. It reveals the “Attached” vs “Unattached” state of the specific device ID.

flutter doctor -v

How Senior Engineers Fix It

  1. Isolate the Physical Layer: Immediately swap the USB cable and try a different USB port (USB 2.0 ports are often more stable for debugging than 3.0 on older hardware).
  2. Reset the ADB Bridge: Don’t restart the whole machine; kill the adb server to force a clean handshake.
    • Run adb kill-server
    • Run adb start-server
    • Run adb devices to verify the device is authorized.
  3. Clean the Pipe: Run flutter clean to wipe build artifacts. While the APK installed, cached connection metadata might be corrupted.
  4. Force Explicit Connection: If flutter run fails to attach, use flutter attach --device-id <your_device_id>. This decouples the build from the attach process, allowing you to see if the VM service is actually listening on a port.
  5. Check for OS Prompts: Look at the phone screen for a “Allow USB Debugging?” prompt or a “Wireless Debugging Pairing” prompt that may be hidden behind other windows.

Why Juniors Miss It

  • Attribution Error: Juniors often assume the code is broken or the project is misconfigured (e.g., “Did I break main.dart?”) because the app UI launches fine. They don’t realize the transport layer (USB/Cable/ADB) is the culprit.
  • Symptom Confusion: They interpret “No Logs” as “App isn’t running,” not “App is running but disconnected from the host.”
  • Reliance on IDE: They rely entirely on VS Code or Android Studio’s visual debug buttons. When those fail, they don’t know how to use the CLI (flutter run --verbose) to see the raw output where connection errors usually appear.