dotnet/wpf · error · InvalidOperationException

SR.FileDialogInvalidFilterIndex

Error message

SR.FileDialogInvalidFilterIndex

What it means

GetFilterExtensions reads the dialog's FilterIndex to pick which filter's extensions to report; if the index is at or beyond the number of parsed filter tokens (i.e. the filter index points at a nonexistent filter), an InvalidOperationException is thrown. FilterIndex is 1-based, with 0 reserved by Windows for the custom-entry slot.

Solutions

  1. Ensure FilterIndex is between 1 and the number of filter pairs in Filter before showing the dialog
  2. Reset FilterIndex to 1 after changing the Filter string
  3. Validate: if (dlg.FilterIndex < 1 || dlg.FilterIndex > countOfFilters) dlg.FilterIndex = 1;
  4. Never assign 0 to FilterIndex (reserved by Windows for custom filters)

Example fix

// before
dlg.Filter = "Text|*.txt";
dlg.FilterIndex = 2; // only 1 filter
// after
dlg.Filter = "Text|*.txt";
dlg.FilterIndex = 1;
Defensive patterns

Strategy: validation

Validate before calling

int filterCount = dlg.Filter.Split('|').Length / 2;
if (dlg.FilterIndex < 1 || dlg.FilterIndex > filterCount)
    dlg.FilterIndex = 1;

Try / catch

try { var files = dlg.FileNames; }
catch (InvalidOperationException ex) when (ex.Message.Contains("filter"))
{
    dlg.FilterIndex = 1; // reset and retry
}

Prevention

When it happens

Trigger: Setting FileDialog.FilterIndex to a value larger than the number of filters in the Filter string before calling ShowDialog or reading FileNames/Extensions; a stale FilterIndex left from a previous dialog configuration whose Filter string was then shortened.

Common situations: Hardcoding FilterIndex = 2 while the Filter has only one entry; programmatically changing Filter after a dialog was used, leaving the old index; off-by-one confusion between 0-based and 1-based indexing.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/FileDialog.cs:712

                // Calculate the index of the token containing extension(s) selected
                // by the FilterIndex property.  Remember FilterIndex is one based.
                // Multiply by 2 because each filter consists of 2 strings.
                // Now subtract one to get to the filter component.
                //
                // example:  Text|*.txt|Pictures|*.jpg|Web Pages|*.htm
                // tokens[]:   0    1       2      3      4        5
                // FilterIndex = 2 selects Pictures;  (2*2)-1 = 3 points to *.jpg in tokens
                //
                int indexOfExtension = (_filterIndex * 2) - 1;

                // Check to be sure our filter index is not out of bounds (that is,
                // greater than the number of filters we actually have).
                // We multiply by 2 here because each filter consists of two strings,
                // description and extensions, both separated by | characters.. so
                // tokens.length is actually twice the number of filters we have.
                if (indexOfExtension >= tokens.Length)
                {
                    throw new InvalidOperationException(SR.FileDialogInvalidFilterIndex);
                }

                // If our filter index is valid (0 is reserved by Windows for custom
                // filter functionality we don't expose, so filters must be 1 or greater)
                if (_filterIndex > 0)
                {
                    // Find our filter in the tokens list, then split it on the
                    // ';' character (which is the filter extension delimiter)
                    ReadOnlySpan<char> exts = tokens[indexOfExtension].AsSpan();

                    foreach (Range ext in exts.Split(';'))
                    {
                        // Filter extensions should be in the form *.txt or .txt,
                        // so we strip out everything before and including the '.'
                        // before adding the extension to our list.
                        // If the extension has no '.', we just ignore it as invalid.
                        int i = exts[ext].LastIndexOf('.');

View on GitHub (pinned to 81131a70a4)