Use when encountering any bug, test failure, or unexpected behavior in Flutter - requires systematic investigation before proposing fixes
Investigates Flutter bugs systematically through root cause analysis before implementing fixes.
/plugin marketplace add vp-k/flutter-craft/plugin install vp-k-flutter-craft-plugins-flutter-craft@vp-k/flutter-craftThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Random fixes waste time and create new bugs. Quick patches mask underlying issues.
Core principle: ALWAYS find root cause before attempting fixes. Symptom fixes are failure.
Announce at start: "I'm using the flutter-debugging skill to investigate this issue."
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
If you haven't completed Phase 1, you cannot propose fixes.
Use for ANY Flutter technical issue:
Use this ESPECIALLY when:
// Basic logging (truncates long output)
print('Debug: $value');
// No truncation (preferred)
debugPrint('Debug: $value');
// Conditional debug logging
import 'package:flutter/foundation.dart';
if (kDebugMode) {
debugPrint('Only in debug mode: $value');
}
// Developer log with tags
import 'dart:developer';
log('API response', name: 'NetworkService', error: e);
# Open DevTools
flutter run --start-paused
# Then press 'd' or use DevTools button in IDE
DevTools Panels:
// Show widget boundaries
debugPaintSizeEnabled = true;
// Show baseline alignments
debugPaintBaselinesEnabled = true;
// Show repaint regions
debugRepaintRainbowEnabled = true;
// Programmatic breakpoint
import 'dart:developer';
debugger();
// Or use IDE breakpoints
BEFORE attempting ANY fix:
════════════════════════════════════════════════════════════
EXCEPTION CAUGHT BY WIDGETS LIBRARY
════════════════════════════════════════════════════════════
The following assertion was thrown building MyWidget:
'package:flutter/src/widgets/container.dart': Failed assertion: line 287
'child != null || decoration != null || constraints != null'
════════════════════════════════════════════════════════════
Don't skip past errors! They often contain the exact solution.
# Hot reload to reproduce
r # in terminal
# Hot restart (clears state)
R # in terminal
# Full restart
flutter run
# What changed recently?
git diff
# Recent commits
git log --oneline -10
# Diff with specific commit
git diff HEAD~3
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
debugPrint('=== MyWidget.build() ===');
debugPrint('context.mounted: ${context.mounted}');
final state = context.watch<MyState>();
debugPrint('state: $state');
return Container(...);
}
}
# Search for similar working code
grep -r "similar_pattern" lib/
// Reference: Working widget
class WorkingWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<WorkingBloc, WorkingState>(
builder: (context, state) => ...,
);
}
}
// Broken: My widget
class BrokenWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// What's different?
return BlocBuilder<MyBloc, MyState>(
builder: (context, state) => ...,
);
}
}
List every difference, however small:
State clearly:
"I think the issue is [X] because [Y]"
Example:
"I think the build error is because the BLoC is not provided above this widget in the widget tree"
Make the SMALLEST possible change:
// Before (broken)
Widget build(BuildContext context) {
final bloc = context.read<MyBloc>();
return ...;
}
// After (testing hypothesis)
Widget build(BuildContext context) {
debugPrint('Looking for MyBloc...');
try {
final bloc = context.read<MyBloc>();
debugPrint('Found: $bloc');
} catch (e) {
debugPrint('Error: $e');
}
return ...;
}
For Repository/DataSource issues (Priority 1):
test('should return user when API succeeds', () async {
// Arrange
when(mockApi.getUser(any)).thenAnswer((_) async => userModel);
// Act
final result = await repository.getUser('123');
// Assert
expect(result, equals(userEntity));
});
ONE change at a time:
// Fix the root cause identified in Phase 3
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => getIt<MyBloc>(),
child: BlocBuilder<MyBloc, MyState>(...),
);
}
}
# Run analysis
flutter analyze
# Run tests
flutter test
# Manual verification
flutter run
# Test the specific scenario
| Symptom | Common Root Cause |
|---|---|
| "No ancestor found" | Provider/BLoC not in widget tree above |
| "setState after dispose" | Async operation completing after widget disposed |
| "RenderBox not laid out" | Unbounded constraints (Column in Column, etc.) |
| "Null check operator" | Variable not initialized or API returned null |
| "Build during build" | setState called during build phase |
| "Ticker not disposed" | Missing with TickerProviderStateMixin or dispose |
If you catch yourself thinking:
ALL of these mean: STOP. Return to Phase 1.
After fixing the bug, you MUST invoke: → flutter-craft:flutter-verification
Verify the fix with flutter analyze, flutter test, and manual testing.
| Phase | Flutter Activities | Success Criteria |
|---|---|---|
| 1. Root Cause | Read error, reproduce, add debugPrint | Understand WHAT and WHY |
| 2. Pattern | Find working widgets, compare | Identify differences |
| 3. Hypothesis | Form theory, minimal test | Confirmed or new hypothesis |
| 4. Implementation | Create test (priority-based), fix, verify | Bug resolved, analysis clean |
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.