.cursor/skills/async-await-patterns/SKILL.md
Enforces async/await patterns over .then() chains, proper error handling, mounted checks. Use when writing async code, handling Futures, or working with async operations.
npx skillsauth add avra-cadavra/avrai async-await-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
✅ ALWAYS use async/await instead of .then() chains
✅ ALWAYS handle errors in async operations (try-catch)
✅ Check mounted before setState() in async callbacks (Flutter widgets)
// ✅ GOOD
Future<void> loadData() async {
try {
final data = await repository.fetch();
if (mounted) {
setState(() => _data = data);
}
} catch (e, st) {
developer.log('Failed to load data', error: e, stackTrace: st);
}
}
// ❌ BAD
void loadData() {
repository.fetch().then((data) {
setState(() => _data = data); // Missing mounted check
}).catchError((e) {
// Silent failure
});
}
Always wrap async operations in try-catch:
Future<Result<User>> getUser(String id) async {
try {
final user = await repository.getUser(id);
return Success(user);
} on NetworkException catch (e) {
return Failure('Network error: ${e.message}');
} catch (e, st) {
developer.log('Unexpected error', error: e, stackTrace: st, name: 'UserService');
return Failure('Failed to load user');
}
}
Always check mounted before setState() in async callbacks:
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
void initState() {
super.initState();
loadData();
}
Future<void> loadData() async {
try {
final data = await repository.fetch();
if (mounted) { // ✅ Check mounted
setState(() {
_data = data;
});
}
} catch (e, st) {
if (mounted) { // ✅ Check mounted
setState(() {
_error = e.toString();
});
}
}
}
}
// ✅ GOOD: Sequential with error handling
Future<void> loadAllData() async {
try {
final user = await loadUser();
final settings = await loadSettings();
final preferences = await loadPreferences();
if (mounted) {
setState(() {
_user = user;
_settings = settings;
_preferences = preferences;
});
}
} catch (e, st) {
developer.log('Failed to load data', error: e, stackTrace: st);
}
}
// ✅ GOOD: Parallel with error handling
Future<void> loadAllDataParallel() async {
try {
final results = await Future.wait([
loadUser(),
loadSettings(),
loadPreferences(),
]);
if (mounted) {
setState(() {
_user = results[0];
_settings = results[1];
_preferences = results[2];
});
}
} catch (e, st) {
developer.log('Failed to load data', error: e, stackTrace: st);
}
}
When method can be sync or async:
FutureOr<String> getData() {
if (_cache != null) {
return _cache!; // Sync return
}
return fetchFromServer(); // Async return
}
Only use Completer when necessary (prefer async/await):
Future<String> convertCallback() {
final completer = Completer<String>();
someCallbackApi((result) {
completer.complete(result);
});
return completer.future;
}
❌ .then() Chains:
repository.fetch()
.then((data) => processData(data))
.then((processed) => saveData(processed))
.catchError((e) => handleError(e)); // BAD
❌ Missing Error Handling:
Future<void> loadData() async {
final data = await repository.fetch(); // No try-catch - BAD
setState(() => _data = data);
}
❌ Missing Mounted Check:
Future<void> loadData() async {
final data = await repository.fetch();
setState(() => _data = data); // No mounted check - BAD
}
❌ Future.value(null).then():
Future.value(null).then((_) => doSomething()); // Use await instead
mounted before setState() in widgetsFutureOr<T> when method can be sync or asyncFuture.wait() for parallel operations.then() chains in new codedevelopment
--- name: world-model-development description: Guides world model development patterns: state/action encoders, ONNX inference, feature extraction pipeline, latency budgets. Use when implementing world model components, state encoders, action encoders, feature extractors, or ONNX models. Core skill for Phases 3-6. --- # World Model Development Patterns ## Core Principle All world model components follow LeCun's autonomous machine intelligence framework. State observations flow through a percep
tools
Implements base workflow controller patterns for multi-step processes. Use when creating complex workflows that require orchestration of multiple steps with error handling and rollback.
testing
--- name: widget-test-patterns description: Guides widget test patterns: BLoC testing, user interactions, state changes, material app setup. Use when writing widget tests, testing UI components, or validating widget behavior. --- # Widget Test Patterns ## Core Pattern Widget tests verify UI behavior: user interactions, state changes, and visual display. ## Basic Widget Test Setup ```dart testWidgets('widget displays correctly', (WidgetTester tester) async { // Arrange: Create widget awa
testing
--- name: test-template-generation description: Generates test templates: unit, widget, integration, service tests following project patterns. Use when creating new tests or ensuring tests follow project standards. --- # Test Template Generation ## Available Templates Test templates are located in `test/templates/`: - `unit_test_template.dart` - `widget_test_template.dart` - `integration_test_template.dart` - `service_test_template.dart` ## Unit Test Template ```dart /// SPOTS Component Uni