Throw when more than one custom factory is applicable
diff --git a/lib/src/custom_watcher_factory.dart b/lib/src/custom_watcher_factory.dart
index ffac06b..b7f81fa 100644
--- a/lib/src/custom_watcher_factory.dart
+++ b/lib/src/custom_watcher_factory.dart
@@ -10,23 +10,20 @@
 
   /// Tries to create a [DirectoryWatcher] for the provided path.
   ///
-  /// Should return `null` if the path is not supported by this factory.
+  /// Returns `null` if the path is not supported by this factory.
   DirectoryWatcher createDirectoryWatcher(String path, {Duration pollingDelay});
 
   /// Tries to create a [FileWatcher] for the provided path.
   ///
-  /// Should return `null` if the path is not supported by this factory.
+  /// Returns `null` if the path is not supported by this factory.
   FileWatcher createFileWatcher(String path, {Duration pollingDelay});
 }
 
 /// Registers a custom watcher.
 ///
-/// It's only allowed to register a watcher once per [id]. The [supportsPath]
-/// will be called to determine if the [createWatcher] should be used instead of
-/// the built-in watchers.
-///
-/// Note that we will try [CustomWatcherFactory] one by one in the order they
-/// were registered.
+/// It's only allowed to register a watcher factory once per [id] and at most
+/// one factory should apply to any given file (creating a [Watcher] will fail
+/// otherwise).
 void registerCustomWatcherFactory(CustomWatcherFactory customFactory) {
   if (_customWatcherFactories.containsKey(customFactory.id)) {
     throw ArgumentError('A custom watcher with id `${customFactory.id}` '
@@ -35,8 +32,48 @@
   _customWatcherFactories[customFactory.id] = customFactory;
 }
 
-/// Unregisters a custom watcher and returns it (returns `null` if it was never
-/// registered).
+/// Tries to create a custom [DirectoryWatcher] and returns it.
+///
+/// Returns `null` if no custom watcher was applicable and throws a [StateError]
+/// if more than one was.
+DirectoryWatcher createCustomDirectoryWatcher(String path,
+    {Duration pollingDelay}) {
+  DirectoryWatcher customWatcher;
+  String customFactoryId;
+  for (var watcherFactory in customWatcherFactories) {
+    if (customWatcher != null) {
+      throw StateError('Two `CustomWatcherFactory`s applicable: '
+          '`$customFactoryId` and `${watcherFactory.id}` for `$path`');
+    }
+    customWatcher =
+        watcherFactory.createDirectoryWatcher(path, pollingDelay: pollingDelay);
+    customFactoryId = watcherFactory.id;
+  }
+  return customWatcher;
+}
+
+/// Tries to create a custom [FileWatcher] and returns it.
+///
+/// Returns `null` if no custom watcher was applicable and throws a [StateError]
+/// if more than one was.
+FileWatcher createCustomFileWatcher(String path, {Duration pollingDelay}) {
+  FileWatcher customWatcher;
+  String customFactoryId;
+  for (var watcherFactory in customWatcherFactories) {
+    if (customWatcher != null) {
+      throw StateError('Two `CustomWatcherFactory`s applicable: '
+          '`$customFactoryId` and `${watcherFactory.id}` for `$path`');
+    }
+    customWatcher =
+        watcherFactory.createFileWatcher(path, pollingDelay: pollingDelay);
+    customFactoryId = watcherFactory.id;
+  }
+  return customWatcher;
+}
+
+/// Unregisters a custom watcher and returns it.
+///
+/// Returns `null` if the id was never registered.
 CustomWatcherFactory unregisterCustomWatcherFactory(String id) =>
     _customWatcherFactories.remove(id);
 
diff --git a/lib/src/directory_watcher.dart b/lib/src/directory_watcher.dart
index 858d020..3fe5004 100644
--- a/lib/src/directory_watcher.dart
+++ b/lib/src/directory_watcher.dart
@@ -30,14 +30,9 @@
   /// watchers.
   factory DirectoryWatcher(String directory, {Duration pollingDelay}) {
     if (FileSystemEntity.isWatchSupported) {
-      for (var custom in customWatcherFactories) {
-        var watcher = custom.createDirectoryWatcher(directory,
-            pollingDelay: pollingDelay);
-        if (watcher != null) {
-          return watcher;
-        }
-      }
-
+      var customWatcher =
+          createCustomDirectoryWatcher(directory, pollingDelay: pollingDelay);
+      if (customWatcher != null) return customWatcher;
       if (Platform.isLinux) return LinuxDirectoryWatcher(directory);
       if (Platform.isMacOS) return MacOSDirectoryWatcher(directory);
       if (Platform.isWindows) return WindowsDirectoryWatcher(directory);
diff --git a/lib/src/file_watcher.dart b/lib/src/file_watcher.dart
index 0b7afc7..c41e5e6 100644
--- a/lib/src/file_watcher.dart
+++ b/lib/src/file_watcher.dart
@@ -30,12 +30,9 @@
   /// and higher CPU usage. Defaults to one second. Ignored for non-polling
   /// watchers.
   factory FileWatcher(String file, {Duration pollingDelay}) {
-    for (var custom in customWatcherFactories) {
-      var watcher = custom.createFileWatcher(file, pollingDelay: pollingDelay);
-      if (watcher != null) {
-        return watcher;
-      }
-    }
+    var customWatcher =
+        createCustomFileWatcher(file, pollingDelay: pollingDelay);
+    if (customWatcher != null) return customWatcher;
 
     // [File.watch] doesn't work on Windows, but
     // [FileSystemEntity.isWatchSupported] is still true because directory
diff --git a/test/custom_watcher_factory_test.dart b/test/custom_watcher_factory_test.dart
index 784769c..6d9ed40 100644
--- a/test/custom_watcher_factory_test.dart
+++ b/test/custom_watcher_factory_test.dart
@@ -1,19 +1,19 @@
 import 'dart:async';
-import 'dart:io';
 
 import 'package:test/test.dart';
 import 'package:watcher/watcher.dart';
 
 void main() {
   _MemFs memFs;
+  final defaultFactoryId = 'MemFs';
 
   setUp(() {
     memFs = _MemFs();
-    registerCustomWatcherFactory(_MemFsWatcherFactory(memFs));
+    registerCustomWatcherFactory(_MemFsWatcherFactory(defaultFactoryId, memFs));
   });
 
   tearDown(() async {
-    unregisterCustomWatcherFactory('MemFs');
+    unregisterCustomWatcherFactory(defaultFactoryId);
   });
 
   test('notifes for files', () async {
@@ -43,8 +43,7 @@
   });
 
   test('unregister works', () async {
-    var memFactory = _MemFsWatcherFactory(memFs);
-    unregisterCustomWatcherFactory(memFactory.id);
+    unregisterCustomWatcherFactory(defaultFactoryId);
 
     var events = <WatchEvent>[];
     var watcher = FileWatcher('file.txt');
@@ -59,9 +58,19 @@
   });
 
   test('registering twice throws', () async {
-    expect(() => registerCustomWatcherFactory(_MemFsWatcherFactory(memFs)),
+    expect(
+        () => registerCustomWatcherFactory(
+            _MemFsWatcherFactory(defaultFactoryId, memFs)),
         throwsA(isA<ArgumentError>()));
   });
+
+  test('finding two applicable factories throws', () async {
+    // Note that _MemFsWatcherFactory always returns a watcher, so having two
+    // will always produce a conflict.
+    registerCustomWatcherFactory(_MemFsWatcherFactory('Different id', memFs));
+    expect(() => FileWatcher('file.txt'), throwsA(isA<StateError>()));
+    expect(() => DirectoryWatcher('dir'), throwsA(isA<StateError>()));
+  });
 }
 
 class _MemFs {
@@ -115,11 +124,9 @@
 }
 
 class _MemFsWatcherFactory implements CustomWatcherFactory {
+  final String id;
   final _MemFs _memFs;
-  _MemFsWatcherFactory(this._memFs);
-
-  @override
-  String get id => 'MemFs';
+  _MemFsWatcherFactory(this.id, this._memFs);
 
   @override
   DirectoryWatcher createDirectoryWatcher(String path,