stride3d/stride · error · ArgumentException

Expecting a single extension

Error message

Expecting a single extension

What it means

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.

Solutions

  1. Pass a single extension string such as ".png"
  2. Split multi-extension strings on ';' or ',' and add each extension separately
  3. Remove any wildcard prefix handling leftovers and add items one at a time

Example fix

// before
collection.Add("*.png;*.jpg");
// after
foreach (var ext in "*.png;*.jpg".Split(';', ',')) collection.Add(ext);
Defensive patterns

Strategy: validation

Validate before calling

if (ext.Contains(';') || ext.Contains(',')) throw new ArgumentException("Pass a single extension", nameof(ext));

Try / catch

try { collection.Add(ext); } catch (ArgumentException) { foreach (var e in ext.Split(';', ',')) collection.Add(e); }

Prevention

When it happens

Trigger: Adding or checking an extension string like "*.png;*.jpg" or "*.png,jpg" via the collection's API (Add/Contains/normalization path called from `normalized`).

Common situations: Copying a file-dialog filter string directly into an asset extension collection; concatenating extensions with ';' separators when building search patterns.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/d7610b8d6179082b. Report an issue: GitHub.

Appendix: source

Thrown at sources/assets/Stride.Core.Assets/IO/FileExtensionCollection.cs:83

    /// <returns>True if the given extension matches, false otherwise.</returns>
    public bool Contains(string extension)
    {
        var normalized = NormalizeExtension(extension);
        var pattern = new Regex(normalized.Replace(".", "[.]").Replace("*", ".*"));
        return SingleExtensions.Any(x => pattern.IsMatch(x) || new Regex(x.Replace(".", "[.]").Replace("*", ".*")).IsMatch(normalized));
    }

    private static List<string> SplitExtensions(string extensions)
    {
        return extensions.Split([';', ','], StringSplitOptions.RemoveEmptyEntries).Select(NormalizeExtension).ToList();
    }

    private static string NormalizeExtension(string extension)
    {
        ArgumentNullException.ThrowIfNull(extension);

        if (extension.Contains(';') || extension.Contains(','))
            throw new ArgumentException("Expecting a single extension");

        if (extension.StartsWith("*.", StringComparison.Ordinal))
        {
            extension = extension[1..];
        }
        if (extension.Any(x => x != '*' & Path.GetInvalidFileNameChars().Contains(x)))
            throw new ArgumentException("Extension contains invalid characters");

        if (!extension.StartsWith('.'))
        {
            extension = $".{extension}";
        }
        return extension.ToLowerInvariant();
    }
}

View on GitHub (pinned to 96fad776d2)