onError method
Called when an exception was occurred during the request.
Implementation
@override
void onError(DioException err, ErrorInterceptorHandler handler) async {
// Check if retry is enabled for this request
final retryEnabled = err.requestOptions.extra['retry'] as bool? ?? config.enableRetry;
if (!retryEnabled) {
// Retry not enabled, pass error through
return handler.next(err);
}
// Get retry count from request options or use global config
final maxRetries = err.requestOptions.extra['retryCount'] as int? ?? config.retryCount;
final currentRetry = err.requestOptions.extra['currentRetry'] as int? ?? 0;
// Check if we should retry this error type
if (!_shouldRetry(err) || currentRetry >= maxRetries) {
logger.log(
'Max retries reached or error not retryable. Giving up.',
isError: true,
);
return handler.next(err);
}
// Calculate delay with exponential backoff if enabled
final baseDelay = err.requestOptions.extra['retryDelay'] as Duration? ?? config.retryDelay;
final useExponentialBackoff = err.requestOptions.extra['exponentialBackoff'] as bool? ??
config.exponentialBackoff;
final delay = useExponentialBackoff
? _calculateExponentialDelay(baseDelay, currentRetry)
: baseDelay;
// Log retry attempt
logger.log(
'🔄 Retrying request (${currentRetry + 1}/$maxRetries) after ${delay.inMilliseconds}ms...',
);
// Wait before retrying
await Future.delayed(delay);
// Create new options with updated retry count
final newOptions = err.requestOptions.copyWith();
newOptions.extra['currentRetry'] = currentRetry + 1;
try {
// Retry the request
final response = await Dio().fetch(newOptions);
return handler.resolve(response);
} on DioException catch (e) {
// If retry also fails, pass it to error handler again
return super.onError(e, handler);
}
}