arch-atlas

Server failure part 2

Data Layer

11:06

Summary

This lesson focuses on improving user experience by returning human-readable error messages for server failures instead of generic, technical exception strings. The instructor refactors the base Failure class to mandate a message property. To avoid duplicating error-parsing logic across repository implementations, he introduces a factory constructor inside ServerFailure that accepts a DioError. By mapping the DioErrorType enum inside a switch statement, the application can return specific, localized messages for network timeouts and connection drops, intentionally deferring the parsing of specific HTTP response errors to the next lesson.

Key Ideas

  • Failure objects should encapsulate user-friendly messages rather than exposing raw stack traces or .toString() dumps.
  • Factory constructors (e.g., ServerFailure.fromDioError) cleanly centralize exception parsing, keeping the Repository layer lean.
  • DioErrorType enum provides granular control over different phases of network failures (e.g., connection, sending, receiving).
  • Timeouts (connectionTimeout, sendTimeout, receiveTimeout) occur before a response is received and require dedicated human-readable error messages.
  • Network absence is mapped via connectionError in recent Dio versions, avoiding the need for manual SocketException checks.

Code Snippets

core/errors/failure.dart - Refactoring Failure to handle specific Dio exceptionsdart
import 'package:dio/dio.dart';

abstract class Failure {
  final String message;

  Failure(this.message);
}

class ServerFailure extends Failure {
  ServerFailure(super.message);

  factory ServerFailure.fromDioError(DioError e) {
    switch (e.type) {
      case DioErrorType.connectionTimeout:
        return ServerFailure('Connection timeout with api server');
      case DioErrorType.sendTimeout:
        return ServerFailure('Send timeout with ApiServer');
      case DioErrorType.receiveTimeout:
        return ServerFailure('Receive timeout with ApiServer');
      case DioErrorType.badCertificate:
        return ServerFailure('badCertificate with api server');
      case DioErrorType.badResponse:
        return ServerFailure('Oops There was an Error, Please try again'); // Implementation deferred to next lesson
      case DioErrorType.cancel:
        return ServerFailure('Request to ApiServer was canceld');
      case DioErrorType.connectionError:
        return ServerFailure('No Internet Connection');
      case DioErrorType.unknown:
        return ServerFailure('Oops There was an Error, Please try again');
    }
  }
}

My Notes

The most valuable architectural pattern demonstrated here is moving the exception-to-failure mapping into a named factory constructor inside the Failure class itself (ServerFailure.fromDioError). This keeps the data sources and repositories incredibly clean, as they only need to catch the exception and pass it to the factory without worrying about the verbose switch mapping logic. [Editor's note] Keep in mind that if you are using Dio v5.0.0 or higher, you must use DioException instead of DioError. The instructor correctly points out new enum types like badCertificate and connectionError, which were added in later Dio updates to natively handle errors that previously fell under unknown or required manual SocketException checks. The badResponse case is intentionally stubbed here with a generic message, as extracting dynamic messages from API error JSON payloads requires a separate strategy based on HTTP status codes.