Gestion des erreurs
Cette bibliothèque mappe les erreurs de l'API Mastodon vers une hiérarchie de classes scellées (sealed classes) dont la racine est MastodonException.
Hiérarchie des exceptions
MastodonException (sealed)
├── MastodonApiException // General HTTP response errors
│ ├── MastodonUnauthorizedException // 401 - Authentication error
│ ├── MastodonForbiddenException // 403 - Permission error
│ ├── MastodonNotFoundException // 404 - Resource not found
│ ├── MastodonRateLimitException // 429 - Rate limited
│ │ ├── retryAfter // Recommended wait duration
│ │ ├── limit // Request limit for the window
│ │ ├── remaining // Remaining requests
│ │ └── resetAt // Time when the window resets
│ ├── MastodonValidationException // 422 - Validation error
│ │ ├── serverMessage // Detailed server message
│ │ ├── details // Field errors by request field
│ │ └── MastodonAlreadyVotedException // Already voted
│ └── MastodonServerException // 5xx - Server error
├── MastodonNetworkException // Network connection error
└── MastodonAuthException (sealed) // OAuth authentication flow errors
├── MastodonAuthCancelledException // User cancelled
├── MastodonAuthStateMismatchException // CSRF detected
└── MastodonAuthTokenException // Token acquisition failed
Modèles de capture de base
Capturer toutes les erreurs
try {
final status = await client.statuses.fetch(id);
} on MastodonException catch (e) {
print('Error: $e');
}
Gérer par code de statut HTTP
try {
final account = await client.accounts.fetchById(accountId);
} on MastodonNotFoundException {
print('Account not found');
} on MastodonUnauthorizedException {
print('Token is invalid. Please re-authenticate');
} on MastodonRateLimitException catch (e) {
print('Rate limited. Retry after ${e.retryAfter}');
} on MastodonApiException catch (e) {
print('API error (${e.statusCode}): ${e.message}');
} on MastodonNetworkException {
print('Check your network connection');
}
Obtenir les détails des erreurs de validation
try {
await client.accounts.create(request);
} on MastodonValidationException catch (e) {
print('Validation error: ${e.serverMessage}');
final details = e.details;
if (details != null) {
for (final entry in details.entries) {
for (final detail in entry.value) {
print('${entry.key}: ${detail.code} - ${detail.description ?? ''}');
}
}
}
}
details est indexé par champ de requête. Chaque
MastodonValidationErrorDetail contient le code d'erreur du serveur et une
description facultative. Les codes inconnus sont conservés sous forme de
chaînes. details vaut null lorsqu'un endpoint ne renvoie pas le format de
détails de validation reconnu de Mastodon.
Exceptions spéciales
MastodonAlreadyVotedException
Levée lorsqu'on tente de voter dans un sondage auquel on a déjà participé.
try {
await client.polls.vote(pollId, [0]);
} on MastodonAlreadyVotedException {
print('Already voted on this poll');
}
Gérer les limites de débit
MastodonRateLimitException expose les en-têtes X-RateLimit-* de Mastodon.
L'attente recommandée utilise Retry-After lorsqu'il est fourni par le serveur
ou le proxy, puis se rabat sur l'horodatage X-RateLimit-Reset.
Future<T> withRetry<T>(Future<T> Function() action) async {
try {
return await action();
} on MastodonRateLimitException catch (e) {
print('${e.remaining}/${e.limit} requêtes restantes ; réinitialisation à ${e.resetAt}');
final wait = e.retryAfter ?? const Duration(seconds: 60);
await Future<void>.delayed(wait);
return action();
}
}
// Usage
final timeline = await withRetry(
() => client.timelines.fetchHome(limit: 20),
);