stride3d/stride · error · ArgumentException

Cannot use as a list of digit

Error message

Cannot use {chars} as a list of digit

What it means

The DigitRange(string) constructor validates that every character of the supplied string is an ASCII digit, since the string is used as the list of allowed digit characters for a terminal matcher. If any non-digit character is present it throws ArgumentException with 'Cannot use {chars} as a list of digit'.

Solutions

  1. Pass only digit characters, enumerating them explicitly: "0123456789"
  2. Use the Range or int constructor overloads (implicit conversions) instead of a string with range syntax
  3. Validate the string with char.IsDigit for each char before constructing

Example fix

// before
var digits = new DigitRange("0-9");
// after
var digits = new DigitRange("0123456789");
Defensive patterns

Strategy: validation

Validate before calling

bool IsDigitList(string s) => s.Length > 0 && s.All(char.IsDigit);
if (!IsDigitList(chars)) throw new ArgumentException($"Cannot use {chars} as a list of digit");

Type guard

bool IsValidDigitRange(string s) => !string.IsNullOrEmpty(s) && s.All(char.IsDigit);

Try / catch

try { var range = new DigitRange(chars); }
catch (ArgumentException ex) { Log(ex.Message); range = new DigitRange("0123456789"); }

Prevention

When it happens

Trigger: Constructing a DigitRange directly or via the implicit string conversion with a string containing letters, signs, spaces, or escapes — e.g. new DigitRange("0-9") (range syntax unsupported), "0x123456789abcdef", or an empty/whitespace-containing string.

Common situations: Authors of custom SDSL terminals writing C-style ranges like "0-9" or "a-f" instead of enumerating digits; accidental copy of regex character-class syntax.

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/af4a673610c8fb7f. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/Parsers/Terminals/Terminals.cs:155

    static string allChars = "0123456789";
    public static DigitRange All { get; } = new(0..9);
    public static DigitRange ExceptZero { get; } = new(1..9);
    public static DigitRange OnlyZero { get; } = new(0);
    public string Chars { get; set; }
    public DigitRange(Range range)
    {
        var (o, l) = range.GetOffsetAndLength(allChars.Length);
        Chars = allChars[o..Math.Min(allChars.Length, o + l + 1)];
    }
    public DigitRange(int digit)
    {
        Chars = $"{(char)(digit + '0')}";
    }
    public DigitRange(string chars)
    {
        foreach (var e in chars)
            if (!char.IsDigit(e))
                throw new ArgumentException($"Cannot use {chars} as a list of digit");
        Chars = chars;
    }

    public static implicit operator DigitRange(Range range) => new(range);
    public static implicit operator DigitRange(int number) => new(number);
    public static implicit operator DigitRange(string numbers) => new(numbers);
}

public record struct DigitTokenParser(DigitRange Mode) : IToken
{
    public readonly bool Match<TScanner>(ref TScanner scanner, bool advance)
        where TScanner : struct, IScanner
    {
        bool found = false;
        if (Mode.Chars.Contains((char)scanner.Peek()))
            found = true;
        if (advance && found)
            scanner.Advance(1);

View on GitHub (pinned to 96fad776d2)