clockworklabs/SpacetimeDB · error · ArgumentOutOfRangeException

Invalid hex character '{c}'.

Error message

Invalid hex character '{c}'.

What it means

QueryBuilder.FormatHexLiteral normalizes a hex string into a SQL hex literal: it strips an optional 0x/0X prefix and all dashes, then requires every remaining character to be 0-9, a-f, or A-F. Any other character (including braces, spaces, 0b prefixes, or quotes) throws ArgumentOutOfRangeException because the result would be an invalid or injectable literal.

Source

Thrown at crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs:868

            throw new ArgumentNullException(nameof(hex));
        }
#endif

        var s = hex;
        if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
        {
            s = s[2..];
        }

        s = s.Replace("-", string.Empty);

        for (var i = 0; i < s.Length; i++)
        {
            var c = s[i];
            var isHex = c is >= '0' and <= '9' or >= 'a' and <= 'f' or >= 'A' and <= 'F';
            if (!isHex)
            {
                throw new ArgumentOutOfRangeException(nameof(hex), $"Invalid hex character '{c}'.");
            }
        }

        return $"0x{s}";
    }

    public static string FormatTimestampLiteral(Timestamp timestamp) =>
        FormatStringLiteral(
            timestamp
                .ToStd()
                .ToUniversalTime()
                .ToString(TimestampFormat, CultureInfo.InvariantCulture)
        );
}

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Pass plain hex digits, optionally with 0x prefix or dashes - nothing else
  2. Use guid.ToString("N") or "D" ("B"/"P" add braces that are not stripped)
  3. Sanitize before calling: strip whitespace, braces, and commas, then regex-validate ^[0-9a-fA-F]+$
  4. Reject user-supplied literals early at the API boundary instead of letting the formatter throw deep in query construction

Example fix

// before
var lit = QueryBuilder.FormatHexLiteral(guid.ToString("B")); // "{...}" braces throw

// after
var lit = QueryBuilder.FormatHexLiteral(guid.ToString("N")); // 32 clean hex digits
Defensive patterns

Strategy: validation

Validate before calling

using System.Text.RegularExpressions;

static bool TryNormalizeHex(string input, out string hex)
{
    var s = input.Trim().Replace("-", "").Replace("{", "").Replace("}", "");
    if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) s = s[2..];
    hex = s;
    return Regex.IsMatch(s, "^[0-9a-fA-F]+$");
}

Prevention

When it happens

Trigger: Passing "0b1010" binary strings; Guid format strings that include braces ("B"/"P" formats like {6a1c...}); input with spaces, commas, or quotes from CSV/JSON copy-paste; strings like "xyz" or "0xGG".

Common situations: Formatting IDs for server-side filters from user input; formatting Guids with ToString("B") instead of "N" or "D"; pasting values that carry invisible whitespace or separators.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/b802bf5f078fb6a8. Report an issue: GitHub.