A small exception class can carry domain context while still implementing Dart's Exception contract.

Program

Play the program to validate a name, then select an empty name to throw the custom exception.

custom_exception.dart
class ValidationError implements Exception {
  final String field;
  ValidationError(this.field);
  @override
  String toString() => 'ValidationError:$field';
}

void requireName(String name) {
  if (name.isEmpty) throw ValidationError('name');
}

void main() {
  var name = ;
  try {
    requireName(name);
    print('ok:$name');
  } catch (e) {
    print(e);
  }
}
class ValidationError implements Exception {
  final String field;
  ValidationError(this.field);
  @override
  String toString() => 'ValidationError:$field';
}

void requireName(String name) {
  if (name.isEmpty) throw ValidationError('name');
}

void main() {
  var name = ;
  try {
    requireName(name);
    print('ok:$name');
  } catch (e) {
    print(e);
  }
}
implements Exception The class can be thrown and caught as an exception.
context field `field` records which validation rule failed.
toString The display text is controlled by overriding `toString`.