{"record":{"id":"a323dbfc261d0072","repo":"dotnet/wpf","slug":"sr-filedialoginvalidfilter","errorCode":null,"errorMessage":"SR.FileDialogInvalidFilter","messagePattern":"SR\\.FileDialogInvalidFilter","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/FileDialog.cs","lineNumber":327,"sourceCode":"            {\n                if (!string.Equals(value, _filter, StringComparison.Ordinal))   // different filter than what we have stored already\n                {\n                    string updatedFilter = value;\n\n                    if (!string.IsNullOrEmpty(updatedFilter))\n                    {\n                        // Require the number of segments of the filter string to be even -\n                        // in other words, there must only be matched pairs of description and\n                        // file extensions.\n                        //\n                        // This implicitly requires there to be at least one vertical bar in\n                        // the filter string - or else formatsCount will be 1, resulting in an\n                        // ArgumentException.\n                        int formatsCount = updatedFilter.AsSpan().Count('|');\n\n                        if (formatsCount % 2 == 0)\n                        {\n                            throw new ArgumentException(SR.FileDialogInvalidFilter);\n                        }\n                    }\n                    else\n                    {   // catch cases like null or \"\" where the filter string is not invalid but\n                        // also not substantive.  We set value to null so that the assignment\n                        // below picks up null as the new value of _filter.\n                        updatedFilter = null;\n                    }\n\n                    _filter = updatedFilter;\n                }\n            }\n        }\n\n        //   Using 1 as the index of the first filter entry is counterintuitive for C#/C++\n        //   developers, but is a side effect of a Win32 feature that allows you to add a template\n        //   filter string that is filled in when the user selects a file for future uses of the dialog.\n        //   We don't support that feature, so only values >1 are valid.","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Microsoft/Win32/FileDialog.cs#L309-L345","documentation":"FileDialog.Filter validates the filter string by counting '|' separators; an even number of pipes means the string does not resolve to description/extension pairs (each pair needs an odd, properly matched set of separators). An ArgumentException is thrown because the filter cannot be parsed into Win32 filter pairs.","triggerScenarios":"Setting OpenFileDialog.Filter (or SaveFileDialog.Filter) to a malformed string, e.g. \"Text files|*.txt|\" (trailing pipe) or \"*.txt\" (no description) or \"A|*.a|B\" (unbalanced pairs).","commonSituations":"Hand-editing a filter string and leaving a stray trailing '|'; building the filter dynamically by concatenation and appending a separator after the last entry; loading filter definitions from config with whitespace/format errors.","solutions":["Use the format \"Description|*.ext1;*.ext2|Description2|*.ext3\" with an odd number of '|' separators forming complete pairs","Remove trailing or doubled '|' characters from the filter string","Ensure every description is followed by at least one extension pattern","Build filters programmatically with string.Join(\"|\", pairs) instead of manual concatenation"],"exampleFix":"// before\ndlg.Filter = \"Text files|*.txt|\"; // trailing pipe -> even count\n// after\ndlg.Filter = \"Text files|*.txt\"; // or \"Text|*.txt|All|*.*\"","handlingStrategy":"validation","validationCode":"bool IsValidFilter(string f) =>\n    !string.IsNullOrWhiteSpace(f) && f.Split('|').Length % 2 == 1 && !f.EndsWith(\"|\");","typeGuard":null,"tryCatchPattern":"try { dlg.Filter = filter; }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"filter\") || ex.ParamName == \"value\")\n{\n    dlg.Filter = \"All files (*.*)|*.*\";\n}","preventionTips":["Build filter strings with string.Join(\"|\", pairs) from a list of (desc, pattern) tuples","Unit-test filter construction logic","Never hand-concatenate '|' characters"],"tags":["wpf","filedialog","filter","argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}