diff --git a/IPA.Loader/Loader/CannotRuntimeDisableException.cs b/IPA.Loader/Loader/CannotRuntimeDisableException.cs
index fe0e9973..da608f19 100644
--- a/IPA.Loader/Loader/CannotRuntimeDisableException.cs
+++ b/IPA.Loader/Loader/CannotRuntimeDisableException.cs
@@ -22,6 +22,13 @@ namespace IPA.Loader
/// the plugin that cannot be disabled
public CannotRuntimeDisableException(PluginMetadata plugin) : base($"Cannot runtime disable plugin \"{plugin.Name}\" ({plugin.Id})")
=> Plugin = plugin;
+ ///
+ /// Creats an exception with the given plugin metadata and message information.
+ ///
+ /// the plugin that cannot be disabled
+ /// the message to associate with it
+ public CannotRuntimeDisableException(PluginMetadata plugin, string message) : base($"{message} \"{plugin.Name}\" ({plugin.Id})")
+ => Plugin = plugin;
///
/// Creates an exception from a serialization context. Not currently implemented.
diff --git a/IPA.Loader/Loader/PluginManager.cs b/IPA.Loader/Loader/PluginManager.cs
index 62002591..72b9ee46 100644
--- a/IPA.Loader/Loader/PluginManager.cs
+++ b/IPA.Loader/Loader/PluginManager.cs
@@ -190,8 +190,11 @@ namespace IPA.Loader
return TaskEx6.FromException(new CannotRuntimeDisableException(exec.Executor.Metadata));
var res = TaskEx.WhenAll(exec.Dependents.Select(d => Disable(d, alreadyDisabled)))
- .ContinueWith(t => TaskEx.WhenAll(t, exec.Executor.Disable()), UnityMainThreadTaskScheduler.Default).Unwrap();
- // The WhenAll above allows us to wait for the executor to disable, but still propagate errors
+ .ContinueWith(t => t.IsFaulted
+ ? TaskEx.WhenAll(t, TaskEx6.FromException(
+ new CannotRuntimeDisableException(exec.Executor.Metadata, "Dependents cannot be disabled for plugin")))
+ : exec.Executor.Disable(), UnityMainThreadTaskScheduler.Default).Unwrap();
+ // We do not want to call the disable method if a dependent couldn't be disabled
// By scheduling on a UnityMainThreadScheduler, we ensure that Disable() is always called on the Unity main thread
alreadyDisabled.Add(exec.Executor, res);
return res;