ワンクリックで
setup-global-catch-error
Configure Superpowers.globalCatchError for centralized error handling, logging, and error conversion
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Configure Superpowers.globalCatchError for centralized error handling, logging, and error conversion
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Add custom error handling with catchError to a mix() call for logging, error conversion, or suppression
Add internet connectivity checking before executing a Cubit method with optional retry
Add debounce to delay method execution until after a period of inactivity for search or validation
Add EffectQueue to state for triggering multiple sequential one-time UI effects
Add Effect fields to state class for one-time UI notifications like snackbars, navigation, or form clearing
Add error state handling to widgets using context.isFailed() and context.getException()
| name | setup-global-catch-error |
| description | Configure Superpowers.globalCatchError for centralized error handling, logging, and error conversion |
This skill configures Superpowers.globalCatchError for centralized error handling across all mix() calls.
Sets up a global error handler that:
mix() callsSet Superpowers.globalCatchError before runApp():
import 'package:bloc_superpowers/bloc_superpowers.dart';
import 'package:flutter/material.dart';
void main() {
Superpowers.globalCatchError = (error, stackTrace, key) {
// Handle the error
};
runApp(
Superpowers(
child: MaterialApp(...),
),
);
}
The handler can respond in three ways:
1. Suppress (return normally): Error is silenced, no dialog shown
Superpowers.globalCatchError = (error, stackTrace, key) {
logError(error, stackTrace);
// Return without throwing = error suppressed
};
2. Show Dialog (throw UserException): Displays error dialog to user
Superpowers.globalCatchError = (error, stackTrace, key) {
logError(error, stackTrace);
throw UserException('Something went wrong');
};
3. Crash (throw other exception): App crashes (useful in debug mode)
Superpowers.globalCatchError = (error, stackTrace, key) {
if (kDebugMode) throw error; // Crash in debug
throw UserException('Something went wrong'); // Dialog in release
};
| Parameter | Type | Description |
|---|---|---|
error | Object | The exception that was thrown |
stackTrace | StackTrace | Where the error originated |
key | Object | The key from the mix() call |
Superpowers.globalCatchError = (error, stackTrace, key) {
// Log to your analytics service
analyticsService.logError(
error: error,
stackTrace: stackTrace,
context: {'key': key.toString()},
);
// Show generic message
if (error is UserException) throw error;
throw UserException('Something went wrong. Please try again.');
};
Superpowers.globalCatchError = (error, stackTrace, key) {
logError(error, stackTrace);
// Firebase Auth errors
if (error is FirebaseAuthException) {
switch (error.code) {
case 'user-not-found':
throw UserException('No account found with this email.');
case 'wrong-password':
throw UserException('Incorrect password.');
case 'user-disabled':
throw UserException('This account has been disabled.');
case 'too-many-requests':
throw UserException('Too many attempts. Try again later.');
default:
throw UserException('Authentication failed.');
}
}
// Dio/HTTP errors
if (error is DioException) {
switch (error.response?.statusCode) {
case 401:
throw UserException('Session expired. Please log in again.');
case 403:
throw UserException('You don\'t have permission for this action.');
case 404:
throw UserException('The requested item was not found.');
case 500:
throw UserException('Server error. Please try again later.');
default:
throw UserException('Network error. Check your connection.');
}
}
// Network errors
if (error is SocketException || error is TimeoutException) {
throw UserException('Could not connect to the server.');
}
// Pass through UserExceptions
if (error is UserException) throw error;
// Generic fallback
throw UserException('Something went wrong. Please try again.');
};
Superpowers.globalCatchError = (error, stackTrace, key) {
// Always log
logger.error('Error in $key', error, stackTrace);
// In debug mode, crash to see the error
if (kDebugMode) {
throw error;
}
// In release, show friendly message
if (error is UserException) throw error;
throw UserException('Something went wrong. Please try again.');
};
Superpowers.globalCatchError = (error, stackTrace, key) {
// Report to Crashlytics
FirebaseCrashlytics.instance.recordError(
error,
stackTrace,
reason: 'Error in mix call: $key',
);
// Or report to Sentry
Sentry.captureException(
error,
stackTrace: stackTrace,
hint: Hint.withMap({'key': key.toString()}),
);
// Convert to user-friendly message
if (error is UserException) throw error;
throw UserException('An error occurred. Our team has been notified.');
};
Errors flow through handlers in order:
Error in mix()
↓
1. Local catchError (in mix call)
↓ (if rethrows)
2. Config catchError (in MixConfig)
↓ (if rethrows)
3. globalCatchError
↓
┌───┴───┐
│ │
returns throws
│ │
↓ ↓
suppressed → isFailed() = true
UserExceptionDialog shows
If any handler suppresses (returns without throwing), subsequent handlers don't run.
import 'package:bloc_superpowers/bloc_superpowers.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
_setupGlobalErrorHandler();
runApp(
Superpowers(
child: MyApp(),
),
);
}
void _setupGlobalErrorHandler() {
Superpowers.globalCatchError = (error, stackTrace, key) {
// 1. Log all errors
_logError(error, stackTrace, key);
// 2. In debug mode, rethrow to see full error
if (kDebugMode && error is! UserException) {
print('Error in $key: $error\n$stackTrace');
}
// 3. Convert known errors to user-friendly messages
final userMessage = _convertToUserMessage(error);
throw UserException(userMessage).addCause(error);
};
}
void _logError(Object error, StackTrace stackTrace, Object key) {
// Log to your service
analyticsService.logError(
error: error,
stackTrace: stackTrace,
context: {'mix_key': key.toString()},
);
}
String _convertToUserMessage(Object error) {
// Pass through existing user messages
if (error is UserException) return error.message;
// Firebase Auth
if (error is FirebaseAuthException) {
return switch (error.code) {
'user-not-found' => 'No account found with this email.',
'wrong-password' => 'Incorrect password.',
'email-already-in-use' => 'An account already exists with this email.',
_ => 'Authentication failed. Please try again.',
};
}
// Network errors
if (error is SocketException) {
return 'No internet connection.';
}
if (error is TimeoutException) {
return 'Request timed out. Please try again.';
}
// HTTP errors
if (error is DioException) {
return switch (error.response?.statusCode) {
401 => 'Please log in to continue.',
403 => 'You don\'t have permission for this action.',
404 => 'The requested item was not found.',
>= 500 => 'Server error. Please try again later.',
_ => 'Network error. Please check your connection.',
};
}
// Generic fallback
return 'Something went wrong. Please try again.';
}
Reset the global handler between tests:
setUp(() {
Superpowers.clear(); // Removes globalCatchError and resets state
});
Ask the user: