-
Notifications
You must be signed in to change notification settings - Fork 0
Error Handling
Flutter AI SDK provides comprehensive error handling with specific error types for different failure scenarios.
AIError (base)
├── AIAuthenticationError - Invalid/expired API key
├── AIRateLimitError - Rate limit exceeded
├── AIContextLengthError - Context too long
├── AIContentFilterError - Content was filtered
├── AIInvalidRequestError - Malformed request
├── AIModelNotFoundError - Model doesn't exist
├── AINetworkError - Network/connectivity issues
├── AIServerError - Provider server error
└── AITimeoutError - Request timed out
try {
final response = await ai.chat('Hello');
print(response.text);
} on AIError catch (e) {
print('AI Error: ${e.message}');
print('Code: ${e.code}');
}Thrown when the API key is invalid or expired.
try {
await ai.chat('Hello');
} on AIAuthenticationError catch (e) {
print('Authentication failed: ${e.message}');
// Prompt user to update API key
}Thrown when you've exceeded the rate limit.
try {
await ai.chat('Hello');
} on AIRateLimitError catch (e) {
print('Rate limited: ${e.message}');
if (e.retryAfter != null) {
print('Retry after: ${e.retryAfter!.inSeconds} seconds');
await Future.delayed(e.retryAfter!);
// Retry the request
}
}Properties:
-
retryAfter- Duration to wait before retrying
Thrown when the context (conversation history) is too long.
try {
await ai.chat('Very long message...');
} on AIContextLengthError catch (e) {
print('Context too long: ${e.message}');
print('Max tokens: ${e.maxTokens}');
print('Requested: ${e.requestedTokens}');
// Clear context and retry
ai.clearContext();
}Properties:
-
maxTokens- Maximum allowed tokens -
requestedTokens- Tokens that were requested
Thrown when content is blocked by safety filters.
try {
await ai.chat(message);
} on AIContentFilterError catch (e) {
print('Content filtered: ${e.message}');
print('Categories: ${e.categories}');
}Properties:
-
categories- List of triggered filter categories
Thrown for network-related issues.
try {
await ai.chat('Hello');
} on AINetworkError catch (e) {
print('Network error: ${e.message}');
if (e.isTimeout) {
print('Request timed out');
}
}Properties:
-
isTimeout- Whether the error was a timeout -
statusCode- HTTP status code (if available)
Thrown when the provider's server has issues.
try {
await ai.chat('Hello');
} on AIServerError catch (e) {
print('Server error: ${e.message}');
print('Status: ${e.statusCode}');
// Usually 500, 502, 503
}Thrown for malformed requests.
try {
await ai.chat('Hello');
} on AIInvalidRequestError catch (e) {
print('Invalid request: ${e.message}');
// Check parameters
}Thrown when the specified model doesn't exist.
try {
await ai.chat('Hello');
} on AIModelNotFoundError catch (e) {
print('Model not found: ${e.message}');
print('Model: ${e.model}');
// Use a different model
}Future<String?> safeChatRequest(FlutterAI ai, String message) async {
try {
final response = await ai.chat(message);
return response.text;
} on AIAuthenticationError catch (e) {
// Handle auth errors
print('Please check your API key');
return null;
} on AIRateLimitError catch (e) {
// Handle rate limiting with retry
if (e.retryAfter != null) {
await Future.delayed(e.retryAfter!);
return safeChatRequest(ai, message); // Retry
}
return null;
} on AIContextLengthError catch (e) {
// Clear context and retry
ai.clearContext();
return safeChatRequest(ai, message);
} on AIContentFilterError catch (e) {
// Content was filtered
print('Your message was filtered');
return null;
} on AINetworkError catch (e) {
// Network issues
print('Please check your internet connection');
return null;
} on AIServerError catch (e) {
// Provider issues
print('Service temporarily unavailable');
return null;
} on AIError catch (e) {
// Catch-all for other AI errors
print('Error: ${e.message}');
return null;
} catch (e) {
// Unexpected errors
print('Unexpected error: $e');
return null;
}
}All AIError subclasses have:
| Property | Type | Description |
|---|---|---|
message |
String |
Human-readable error message |
code |
String? |
Error code from provider |
details |
Map<String, dynamic>? |
Additional error details |
stackTrace |
StackTrace? |
Stack trace for debugging |
Implement automatic retry for transient errors:
Future<AIResponse> chatWithRetry(
FlutterAI ai,
String message, {
int maxRetries = 3,
}) async {
for (var attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await ai.chat(message);
} on AIRateLimitError catch (e) {
if (attempt == maxRetries) rethrow;
final delay = e.retryAfter ?? Duration(seconds: attempt * 2);
await Future.delayed(delay);
} on AINetworkError catch (e) {
if (attempt == maxRetries) rethrow;
if (e.isTimeout) {
await Future.delayed(Duration(seconds: attempt));
} else {
rethrow;
}
} on AIServerError catch (e) {
if (attempt == maxRetries) rethrow;
await Future.delayed(Duration(seconds: attempt * 2));
}
}
throw Exception('Max retries exceeded');
}Handle errors in streaming responses:
try {
await for (final chunk in ai.streamChat(message)) {
if (chunk.isError) {
throw chunk.error!;
}
if (chunk.isDelta) {
print(chunk.delta);
}
}
} on AIError catch (e) {
print('Stream error: ${e.message}');
}Implement comprehensive error logging:
void logAIError(AIError error) {
final log = StringBuffer()
..writeln('=== AI Error ===')
..writeln('Type: ${error.runtimeType}')
..writeln('Message: ${error.message}')
..writeln('Code: ${error.code}');
if (error.details != null) {
log.writeln('Details: ${error.details}');
}
if (error is AIRateLimitError && error.retryAfter != null) {
log.writeln('Retry After: ${error.retryAfter!.inSeconds}s');
}
if (error is AIContextLengthError) {
log.writeln('Max Tokens: ${error.maxTokens}');
log.writeln('Requested: ${error.requestedTokens}');
}
print(log);
}Show user-friendly error messages:
String getUserFriendlyMessage(AIError error) {
return switch (error) {
AIAuthenticationError() =>
'Unable to connect. Please check your API key.',
AIRateLimitError() =>
'Too many requests. Please wait a moment.',
AIContextLengthError() =>
'Conversation too long. Starting fresh.',
AIContentFilterError() =>
'Your message couldn\'t be processed.',
AINetworkError() =>
'Connection issue. Check your internet.',
AIServerError() =>
'Service temporarily unavailable.',
_ => 'Something went wrong. Please try again.',
};
}
// In your widget
try {
final response = await ai.chat(message);
setState(() => _response = response.text);
} on AIError catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(getUserFriendlyMessage(e))),
);
}- API-Errors - Full error API reference
- Configuration - Timeout settings
Getting Started
Core Concepts
Advanced Features
API Reference
Examples
Other