dotnet/wpf · error · IndexOutOfRangeException

IndexOutOfRangeException

Error message

IndexOutOfRangeException

What it means

GenerateFallbackUri walks previously registered theme dictionaries to build a fallback URI from their resource name. It expects the stored resource name to contain at least two '/'-delimited segments (it splits and indexes segment [1]). When fewer segments exist, the bare IndexOutOfRangeException is thrown — effectively an internal invariant violation.

Solutions

  1. Ensure the Source URIs of theme dictionaries contain at least two path segments (e.g. 'pack://application:,,,/Assembly;component/Themes/ThemeName.xaml').
  2. Locate the offending registered dictionary and correct its Source path.
  3. Catch this during theme-switch code paths and fall back to a fully qualified pack URI.

Example fix

// before
dictionary.Source = new Uri("pack://application:,,,/App;component/flat.xaml");
// after
dictionary.Source = new Uri("pack://application:,,,/App;component/Themes/Custom.xaml");
Defensive patterns

Strategy: try-catch

Validate before calling

var segments = dictionary.Source?.AbsolutePath?.Split('/');
if (segments == null || segments.Length < 2)
    throw new InvalidOperationException("Theme dictionary source needs >= 2 path segments for fallback resolution.");

Try / catch

try { var uri = GenerateFallbackUri(dictionary, resourceName); }
catch (IndexOutOfRangeException) { return GenerateUri(assemblyName, resourceName, defaultTheme); }

Prevention

When it happens

Trigger: A dictionary registered via Register() whose resourceName lacks a second path segment (e.g. 'themes.xaml' instead of 'themes/light.xaml') when a fallback URI is generated after a theme change.

Common situations: Custom or legacy theme dictionary registrations with flat resource names; mismatch between a hand-built dictionary source path and what UxThemeWrapper expects during fallback theme resolution.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/731dc898d4bbc507. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ThemeDictionaryExtension.cs:136

        internal static Uri GenerateFallbackUri(ResourceDictionary dictionary, string resourceName)
        {
            Span<Range> splitRegions = stackalloc Range[3];
            for (int i = 0; i < _themeDictionaryInfos.Count; i++)
            {
                ThemeDictionaryInfo info = _themeDictionaryInfos[i];

                if (!info.DictionaryReference.IsAlive)
                {
                    // Remove from list
                    _themeDictionaryInfos.RemoveAt(i);
                    i--;
                    continue;
                }
                if ((ResourceDictionary)info.DictionaryReference.Target == dictionary)
                {
                    ReadOnlySpan<char> nameSpan = resourceName.AsSpan();
                    if (nameSpan.Split(splitRegions, '/') < 2)
                        throw new IndexOutOfRangeException();

                    return GenerateUri(info.AssemblyName, resourceName, nameSpan[splitRegions[1]]);
                }
            }
            return null;
        }


        #endregion

        #region Data

        private string _assemblyName;

        #endregion

        #region Static Data

View on GitHub (pinned to 81131a70a4)