By Abdelrahman Saed — Senior Mobile Engineer. Last updated: 2026-08-10.
Either<Failure, T> is a functional error-handling pattern from the dartz package where a function returns either a Left (containing a Failure) or a Right (containing the success value T). Instead of throwing exceptions on errors, you return them as values — making every error path an explicit fork the caller must handle.
Either<L, R> is a union type — it holds either a Left value or a Right value, never both. By convention, Left holds the error (Failure) and Right holds the success (T):
// A repository method returning Either<Failure, T>
Future<Either<Failure, List<Story>>> fetchStories() async {
try {
final stories = await _local.cachedStories();
return Right(stories); // success
} on CacheException catch (e) {
return Left(CacheFailure(e.message)); // failure as a value
}
}
// The caller must handle both cases
final result = await repository.fetchStories();
result.fold(
(failure) => showError(failure.message),
(stories) => showStories(stories),
);
The critical difference from exceptions: the compiler doesn't force you to handle an exception, but the type system forces you to handle an Either. You can't access the success value without acknowledging that a failure might exist.
At iStoria (99.9% crash-free across 350+ releases), this pattern is a core reason the app is stable. Every repository returns Either<Failure, T>. The UI renders failure states the same way it renders success states — there is no unhandled exception path that can crash the app.
A typical failure hierarchy:
abstract class Failure {
final String message;
Failure(this.message);
}
class NetworkFailure extends Failure {
NetworkFailure(super.message);
}
class CacheFailure extends Failure {
CacheFailure(super.message);
}
class ServerFailure extends Failure {
ServerFailure(super.message);
}
Use Either<Failure, T> when:
Skip it when:
fpdart is the modern choice — it is actively maintained, has better Dart 3 integration (sealed classes, pattern matching), and offers additional types like TaskEither and Option. dartz works but hasn't been updated in years. At iStoria, we started with dartz; new features use fpdart.
It replaces throwing exceptions across layer boundaries. Inside a data source (network client, database), you still use try/catch — you catch the exception and wrap it in a Left(Failure). The Either is the contract between layers; try/catch is the implementation inside a layer.
Available for hire. Abdelrahman Saed is a Senior Mobile Engineer (Flutter) — open to full-time, fractional, contract, or advisory work. Hire me →
Book a 20-minute call · Download the CV (PDF) · See how I work