| name | flutter-bug-investigation |
| description | Use when investigating bugs, crashes, or unexpected behavior in a Flutter app. Especially when issues involve Bloc state not emitting, null safety errors, BuildContext after async, GetIt DI failures, method channel mismatches, widget rebuilds, or memory leaks. |
Bug Solving Skill (Flutter)
Foundation: Extends shared-bug-investigation with Flutter patterns.
Flutter Context
flutter --version && grep "sdk:" pubspec.yaml
grep -r "BlocProvider\|ChangeNotifier\|GetX" lib/
RCA: Check All Layers (data/domain/view)
find lib/feature/<feature>/view -name "*.dart"
find lib/feature/<feature>/domain -name "*.dart"
find lib/feature/<feature>/data -name "*.dart"
Debug by layer: View (Bloc emits?) → Domain (model mapping?) → Data (DTO parsing?)
Common Bug Patterns
Bloc State
// ❌ Missing emit → ✅ Add emit(LoadingState()), emit(LoadedState(data)), emit(ErrorState())
Null Safety
// ❌ user!.name → ✅ user?.name ?? 'Guest'
BuildContext After Async
// ❌ Navigator.pop(context) after await → ✅ if (!mounted) return; Navigator.pop(context);
GetIt DI
// ❌ Not registered → ✅ Add @injectable, run build_runner
Method Channels
// ❌ Wrong name → ✅ Match iOS/Android channel name
Widget Rebuilds
// ❌ BlocBuilder wraps Scaffold → ✅ Wrap only body
Memory Leaks
// ❌ Stream not closed → ✅ Override close(), call super.close()
Error Quick Reference
| Error | Fix |
|---|
type 'Null' is not a subtype | Add ?? defaults |
Looking up deactivated widget | Check mounted |
Object not registered | Add @injectable, run build_runner |
MissingPluginException | Implement native iOS/Android |
setState() after dispose() | Cancel timers/streams |
RenderBox overflow | Fix constraints |
Tools
flutter analyze
flutter test
flutter run --profile
Validation