Flow-Launcher/Flow.Launcher · error · InvalidOperationException
Unable to load settings for plugin: {pluginPair.Metadata.Nam
Error message
Unable to load settings for plugin: {pluginPair.Metadata.Name} What it means
Thrown by the PluginSettingsWindow constructor when _settings.PluginSettings.GetPluginSettings(pluginId) returns null even though the plugin itself is loaded. The plugin was found (so error 28 did not fire) but no settings object was registered for it. This typically means the plugin has no settings schema, its settings JSON could not be deserialised, or the registration step was skipped during plugin load.
Source
Thrown at Flow.Launcher/PluginSettingsWindow.xaml.cs:37
{
_settings = Ioc.Default.GetRequiredService<Settings>();
if (string.IsNullOrWhiteSpace(pluginId)){
throw new ArgumentException("Plugin ID cannot be null or whitespace.", nameof(pluginId));
}
PluginId = pluginId;
var pluginPair = PluginManager.GetPluginForId(pluginId);
if (pluginPair == null)
{
throw new InvalidOperationException($"Unable to find plugin: {pluginId}");
}
var pluginSettings = _settings.PluginSettings.GetPluginSettings(pluginId);
if (pluginSettings == null)
{
throw new InvalidOperationException($"Unable to load settings for plugin: {pluginPair.Metadata.Name}");
}
var pluginViewModel = new PluginViewModel
{
PluginPair = pluginPair,
PluginSettingsObject = pluginSettings,
IsExpanded = true,
};
DataContext = pluginViewModel;
Title = Localize.pluginSettingsWindowTitle(pluginPair.Metadata.Name);
InitializeComponent();
}
// This is used for Priority control to force its value to be 0 when the user clears the value.
private void NumberBox_OnValueChanged(NumberBox sender, NumberBoxValueChangedEventArgs args)
{
if (double.IsNaN(args.NewValue))View on GitHub (pinned to 7fc63b07bb)
Solutions
- Make GetPluginSettings return a default empty settings object instead of null so the UI can always open.
- Validate the settings file existence/JSON before opening the window and offer to reset on corruption.
- Catch the InvalidOperationException at the caller and show a recovery dialog (reset settings).
- Log the deserialisation error with the pluginId and the JSON path so failures are not silent.
Example fix
// before
var pluginSettings = _settings.PluginSettings.GetPluginSettings(pluginId);
if (pluginSettings == null)
{
throw new InvalidOperationException($"Unable to load settings for plugin: {pluginPair.Metadata.Name}");
}
// after - recover with a fresh default instead of throwing
var pluginSettings = _settings.PluginSettings.GetPluginSettings(pluginId)
?? _settings.PluginSettings.ResetPluginSettings(pluginId); Defensive patterns
Strategy: fallback
Validate before calling
var settingsFile = Path.Combine(pluginDir, pluginId, "Settings", "plugin.json");
if (!File.Exists(settingsFile)) logger.Warn($"Settings file missing for {pluginId}"); Type guard
static bool HasSettingsRegistered(string pluginId) => Ioc.Default.GetRequiredService<Settings>().PluginSettings.GetPluginSettings(pluginId) is not null;
Try / catch
try { new PluginSettingsWindow(pluginId).Show(); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Unable to load settings"))
{
if (App.API.ShowMsg("Settings are corrupt. Reset?", "Yes")) _settings.PluginSettings.ResetPluginSettings(pluginId);
} Prevention
- Have GetPluginSettings return a default object instead of null.
- Validate the settings JSON before opening the window.
- Catch the exception and offer a reset.
- Log deserialisation errors with the plugin ID and file path.
When it happens
Trigger: The plugin's settings file is missing or empty (first run after install), the JSON is malformed and deserialisation silently produced null, the plugin does not implement a settings class but the UI still tries to edit it, or a plugin upgrade changed the settings type so the old payload no longer maps.
Common situations: Fresh install of a plugin whose settings file is created lazily; user manually deleted the plugin's Settings/*.json; plugin version bump renamed the settings class so the old JSON deserialises to null; the plugin declares PluginSettings but did not register it with PluginSettings during LoadPlugin.
Related errors
- Unable to find plugin: {pluginId}
- Failed to deserialize double pinyin table: result is null
- SHParseDisplayName failed
- SHBindToParent failed
- GetUIObjectOf failed
AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13).
Data as JSON: /api/errors/196f997edb273733.
Report an issue: GitHub.