{"record":{"id":"a6475200ced79421","repo":"tursodatabase/turso","slug":"only-finite-numbers-not-infinity-or-nan-can-be-p-a64752","errorCode":null,"errorMessage":"Only finite numbers (not Infinity or NaN) can be passed as arguments","messagePattern":"Only finite numbers \\(not Infinity or NaN\\) can be passed as arguments","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Serverless.Client/HranaProtocol.cs","lineNumber":41,"sourceCode":"\n    public static readonly HranaValue Null = new() { Type = \"null\" };\n\n    public static HranaValue Encode(object? value)\n    {\n        switch (value)\n        {\n            case null or DBNull:\n                return Null;\n            case bool b:\n                return new HranaValue { Type = \"integer\", StringValue = b ? \"1\" : \"0\" };\n            case sbyte or byte or short or ushort or int or uint or long:\n                return new HranaValue { Type = \"integer\", StringValue = Convert.ToInt64(value, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture) };\n            case ulong ul:\n                return new HranaValue { Type = \"integer\", StringValue = ul.ToString(CultureInfo.InvariantCulture) };\n            case float f:\n                return double.IsFinite(f)\n                    ? new HranaValue { Type = \"float\", DoubleValue = f }\n                    : throw new ArgumentException(\"Only finite numbers (not Infinity or NaN) can be passed as arguments\");\n            case double d:\n                return double.IsFinite(d)\n                    ? new HranaValue { Type = \"float\", DoubleValue = d }\n                    : throw new ArgumentException(\"Only finite numbers (not Infinity or NaN) can be passed as arguments\");\n            case decimal m:\n                return new HranaValue { Type = \"float\", DoubleValue = (double)m };\n            case string s:\n                return new HranaValue { Type = \"text\", StringValue = s };\n            case char c:\n                return new HranaValue { Type = \"text\", StringValue = c.ToString() };\n            case Guid g:\n                return new HranaValue { Type = \"text\", StringValue = g.ToString() };\n            case DateTime dt:\n                return new HranaValue { Type = \"text\", StringValue = dt.ToString(\"o\", CultureInfo.InvariantCulture) };\n            case DateTimeOffset dto:\n                return new HranaValue { Type = \"text\", StringValue = dto.ToString(\"o\", CultureInfo.InvariantCulture) };\n            case byte[] bytes:\n                return new HranaValue { Type = \"blob\", BlobValue = bytes };","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/dotnet/src/Turso.Serverless.Client/HranaProtocol.cs#L23-L59","documentation":"The .NET serverless client encodes SQL parameters into Hrana protocol JSON before sending them. The JSON specification has no literals for Infinity or NaN, so the encoder refuses any non-finite float instead of producing a payload the server could never parse. The exception is thrown client-side, before any network request is made.","triggerScenarios":"Passing float.NaN, float.PositiveInfinity, or float.NegativeInfinity as a command parameter, e.g. cmd.Parameters.AddWithValue(\"@v\", float.NaN) followed by ExecuteAsync. Also triggered when a float is boxed as object and reaches the pattern match in the float case.","commonSituations":"Aggregating sensor/financial data with gaps that become NaN (0f/0f, missing readings), parsing external JSON that yields NaN, or porting code from System.Data.SQLite which historically coerced NaN to NULL instead of throwing.","solutions":["Map non-finite floats to a sentinel before binding: DBNull.Value for NULL, or 0/text per your schema","Validate with float.IsFinite(value) at the boundary where the value enters your application","If NaN/Infinity must be stored, encode them as TEXT (e.g. \"NaN\") in a TEXT column","Fix the upstream computation producing NaN/Infinity — usually a divide-by-zero or an uninitialized accumulator"],"exampleFix":"// before\nfloat ratio = total / count; // 0/0 -> NaN\ncmd.Parameters.AddWithValue(\"@r\", ratio);\n\n// after\nfloat ratio = count == 0 ? 0f : total / count;\ncmd.Parameters.AddWithValue(\"@r\", ratio);","handlingStrategy":"type-guard","validationCode":"float SafeFloat(float v) => float.IsFinite(v) ? v : throw new ArgumentOutOfRangeException(nameof(v), \"non-finite float\");","typeGuard":"static bool IsBindableFloat(float value) => float.IsFinite(value);","tryCatchPattern":"try { cmd.Parameters.AddWithValue(\"@v\", v); } catch (ArgumentException) when (v is float f && !float.IsFinite(f)) { cmd.Parameters.AddWithValue(\"@v\", DBNull.Value); }","preventionTips":["Validate floats at ingestion boundaries with IsFinite","Keep NaN sentinels out of the data layer; convert to NULL or domain defaults on entry","Add unit tests asserting parameters never receive non-finite values"],"tags":["csharp","dotnet","hrana-protocol","parameter-binding","json"],"backgroundTag":"binding-nan-or-infinity","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}