{"record":{"id":"b802bf5f078fb6a8","repo":"clockworklabs/SpacetimeDB","slug":"invalid-hex-character-c","errorCode":null,"errorMessage":"Invalid hex character '{c}'.","messagePattern":"Invalid hex character '(.+?)'\\.","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs","lineNumber":868,"sourceCode":"            throw new ArgumentNullException(nameof(hex));\n        }\n#endif\n\n        var s = hex;\n        if (s.StartsWith(\"0x\", StringComparison.OrdinalIgnoreCase))\n        {\n            s = s[2..];\n        }\n\n        s = s.Replace(\"-\", string.Empty);\n\n        for (var i = 0; i < s.Length; i++)\n        {\n            var c = s[i];\n            var isHex = c is >= '0' and <= '9' or >= 'a' and <= 'f' or >= 'A' and <= 'F';\n            if (!isHex)\n            {\n                throw new ArgumentOutOfRangeException(nameof(hex), $\"Invalid hex character '{c}'.\");\n            }\n        }\n\n        return $\"0x{s}\";\n    }\n\n    public static string FormatTimestampLiteral(Timestamp timestamp) =>\n        FormatStringLiteral(\n            timestamp\n                .ToStd()\n                .ToUniversalTime()\n                .ToString(TimestampFormat, CultureInfo.InvariantCulture)\n        );\n}\n","sourceCodeStart":850,"sourceCodeEnd":883,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs#L850-L883","documentation":"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.","triggerScenarios":"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\".","commonSituations":"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.","solutions":["Pass plain hex digits, optionally with 0x prefix or dashes - nothing else","Use guid.ToString(\"N\") or \"D\" (\"B\"/\"P\" add braces that are not stripped)","Sanitize before calling: strip whitespace, braces, and commas, then regex-validate ^[0-9a-fA-F]+$","Reject user-supplied literals early at the API boundary instead of letting the formatter throw deep in query construction"],"exampleFix":"// before\nvar lit = QueryBuilder.FormatHexLiteral(guid.ToString(\"B\")); // \"{...}\" braces throw\n\n// after\nvar lit = QueryBuilder.FormatHexLiteral(guid.ToString(\"N\")); // 32 clean hex digits","handlingStrategy":"validation","validationCode":"using System.Text.RegularExpressions;\n\nstatic bool TryNormalizeHex(string input, out string hex)\n{\n    var s = input.Trim().Replace(\"-\", \"\").Replace(\"{\", \"\").Replace(\"}\", \"\");\n    if (s.StartsWith(\"0x\", StringComparison.OrdinalIgnoreCase)) s = s[2..];\n    hex = s;\n    return Regex.IsMatch(s, \"^[0-9a-fA-F]+$\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate hex with a regex at the input boundary before query construction","Format Guids with ToString(\"N\") or \"D\" - never \"B\"/\"P\" which add braces","Reject strings containing prefixes other than 0x early with a clear API error"],"tags":["csharp","query-builder","hex-input","sql-literal","spacetimedb"],"backgroundTag":"invalid-hex-input","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}