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
- Pass only digit characters, enumerating them explicitly: "0123456789"
- Use the Range or int constructor overloads (implicit conversions) instead of a string with range syntax
- 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
- Never pass regex-style ranges like "0-9"; enumerate digits explicitly
- Prefer the Range or int constructor overloads over raw strings
- Reject/escape user-supplied character-set strings before constructing
- Add a unit test asserting each char of every DigitRange constant is a digit
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
- Expecting a single extension
- Extension contains invalid characters
- 's must be finite and greater than zero
- Value must be > 0
- This method must be invoked with at least one property name.
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)