MahApps/MahApps.Metro · error · InvalidOperationException
Unable to find the dialog closing storyboard. Did you forget
Error message
Unable to find the dialog closing storyboard. Did you forget to add BaseMetroDialog.xaml to your merged dictionaries?
What it means
WaitForCloseAsync animates a dialog's hide using the 'MahApps.Storyboard.Dialogs.Close' resource. When DialogSettings.AnimateHide is true but TryFindResource returns nothing (the resource key is absent from the dialog's resources), it throws InvalidOperationException pointing at the missing BaseMetroDialog.xaml. The resource ships inside the MahApps.Metro dialog templates, so its absence means the templates were not merged into the application's resource dictionaries.
Source
Thrown at src/MahApps.Metro/Controls/Dialogs/BaseMetroDialog.cs:514
{
var tcs = new TaskCompletionSource<object>();
this.Unloaded += (_, _) => { tcs.TrySetResult(null!); };
return tcs.Task;
}
private EventHandler? closingStoryboardOnCompleted;
public Task WaitForCloseAsync()
{
var tcs = new TaskCompletionSource<object>();
if (this.DialogSettings.AnimateHide)
{
if (this.TryFindResource("MahApps.Storyboard.Dialogs.Close") is not Storyboard closingStoryboard)
{
throw new InvalidOperationException("Unable to find the dialog closing storyboard. Did you forget to add BaseMetroDialog.xaml to your merged dictionaries?");
}
closingStoryboard = closingStoryboard.Clone();
this.closingStoryboardOnCompleted = (_, _) =>
{
closingStoryboard.Completed -= this.closingStoryboardOnCompleted;
tcs.TrySetResult(null!);
};
closingStoryboard.Completed += this.closingStoryboardOnCompleted;
closingStoryboard.Begin(this);
}
else
{
this.SetCurrentValue(OpacityProperty, 0.0);View on GitHub (pinned to 72099e310b)
Solutions
- Merge the MahApps.Metro dialog resource dictionaries into App.xaml (e.g. <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml"/>) so the storyboard key is available globally.
- If you use a custom dialog template, ensure it (or its merged dictionaries) defines the 'MahApps.Storyboard.Dialogs.Close' Storyboard.
- Alternatively set DialogSettings.AnimateHide = false to skip the animation path that needs the storyboard.
- Verify the correct MahApps.Metro version is referenced; the resource key exists in the shipped BaseMetroDialog.xaml.
Example fix
<!-- before: dialogs work but AnimateHide throws on close -->
<Application.Resources/>
<!-- after: merge the MahApps control/dialog resources -->
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources> Defensive patterns
Strategy: validation
Validate before calling
// Ensure the closing storyboard resource is resolvable before enabling AnimateHide
bool hasCloseStoryboard = dialog.TryFindResource("MahApps.Storyboard.Dialogs.Close") is Storyboard;
dialog.DialogSettings.AnimateHide = hasCloseStoryboard;
dialog.DialogSettings.AnimateShow = hasCloseStoryboard; Try / catch
try {
await dialogCoordinator.HideMetroDialogAsync(context, dialog);
} catch (InvalidOperationException ex) when (ex.Message.Contains("closing storyboard")) {
// fall back to non-animated close
dialog.DialogSettings.AnimateHide = false;
await dialogCoordinator.HideMetroDialogAsync(context, dialog);
} Prevention
- Merge the MahApps.Metro dialog/control resource dictionaries into App.xaml so the storyboard key is global.
- If you ship a custom dialog template, keep the 'MahApps.Storyboard.Dialogs.Close' Storyboard resource in it.
- Disable AnimateHide/AnimateShow if your resource set lacks the storyboard rather than letting it throw.
- Pin the MahApps.Metro version whose resource keys you author templates against.
When it happens
Trigger: A BaseMetroDialog (or subclass) is shown with AnimateHide == true, and when it closes WaitForCloseAsync cannot find the 'MahApps.Storyboard.Dialogs.Close' Storyboard resource — typically because the MahApps.Metro dialog resource dictionaries were not merged into App.xaml or the dialog's own resources.
Common situations: App uses MahApps dialogs but forgot to merge MahApps.Metro.Resources.Dialogs (or the BaseMetroDialog template) into MergedDictionaries. A custom dialog template removed the closing storyboard. Resource cleanup/replacement dropped the key. An older MahApps version whose key name differs.
Related errors
- Uups, it seems like there is something wrong with the given
- Cannot convert the given input to a valid color
- The inverse dialog theme only works if the window theme abid
- The context `{context}` is not registered. Consider using th
- The context `{context}` is not inside a MetroWindow.
AI-assisted analysis of MahApps/MahApps.Metro@72099e310b (2026-08-13).
Data as JSON: /api/errors/5754eb4e36c50c12.
Report an issue: GitHub.