{"record":{"id":"d7610b8d6179082b","repo":"stride3d/stride","slug":"expecting-a-single-extension","errorCode":null,"errorMessage":"Expecting a single extension","messagePattern":"Expecting a single extension","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets/IO/FileExtensionCollection.cs","lineNumber":83,"sourceCode":"    /// <returns>True if the given extension matches, false otherwise.</returns>\n    public bool Contains(string extension)\n    {\n        var normalized = NormalizeExtension(extension);\n        var pattern = new Regex(normalized.Replace(\".\", \"[.]\").Replace(\"*\", \".*\"));\n        return SingleExtensions.Any(x => pattern.IsMatch(x) || new Regex(x.Replace(\".\", \"[.]\").Replace(\"*\", \".*\")).IsMatch(normalized));\n    }\n\n    private static List<string> SplitExtensions(string extensions)\n    {\n        return extensions.Split([';', ','], StringSplitOptions.RemoveEmptyEntries).Select(NormalizeExtension).ToList();\n    }\n\n    private static string NormalizeExtension(string extension)\n    {\n        ArgumentNullException.ThrowIfNull(extension);\n\n        if (extension.Contains(';') || extension.Contains(','))\n            throw new ArgumentException(\"Expecting a single extension\");\n\n        if (extension.StartsWith(\"*.\", StringComparison.Ordinal))\n        {\n            extension = extension[1..];\n        }\n        if (extension.Any(x => x != '*' & Path.GetInvalidFileNameChars().Contains(x)))\n            throw new ArgumentException(\"Extension contains invalid characters\");\n\n        if (!extension.StartsWith('.'))\n        {\n            extension = $\".{extension}\";\n        }\n        return extension.ToLowerInvariant();\n    }\n}\n","sourceCodeStart":65,"sourceCodeEnd":99,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets/IO/FileExtensionCollection.cs#L65-L99","documentation":"FileExtensionCollection.NormalizeExtension validates each extension string passed to the collection. Extensions containing ';' or ',' look like multi-extension wildcard patterns (as used in file dialogs), which this collection does not accept, so it throws ArgumentException.","triggerScenarios":"Adding or checking an extension string like \"*.png;*.jpg\" or \"*.png,jpg\" via the collection's API (Add/Contains/normalization path called from `normalized`).","commonSituations":"Copying a file-dialog filter string directly into an asset extension collection; concatenating extensions with ';' separators when building search patterns.","solutions":["Pass a single extension string such as \".png\"","Split multi-extension strings on ';' or ',' and add each extension separately","Remove any wildcard prefix handling leftovers and add items one at a time"],"exampleFix":"// before\ncollection.Add(\"*.png;*.jpg\");\n// after\nforeach (var ext in \"*.png;*.jpg\".Split(';', ',')) collection.Add(ext);","handlingStrategy":"validation","validationCode":"if (ext.Contains(';') || ext.Contains(',')) throw new ArgumentException(\"Pass a single extension\", nameof(ext));","typeGuard":null,"tryCatchPattern":"try { collection.Add(ext); } catch (ArgumentException) { foreach (var e in ext.Split(';', ',')) collection.Add(e); }","preventionTips":["Never reuse file-dialog filter strings as extension collections","Split multi-extension inputs before adding","Validate user-provided extensions early"],"tags":["validation","file-extension","argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}