tursodatabase/turso · error · ArgumentException
Only finite numbers (not Infinity or NaN) can be passed as a
Error message
Only finite numbers (not Infinity or NaN) can be passed as arguments
What it means
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.
Source
Thrown at bindings/dotnet/src/Turso.Serverless.Client/HranaProtocol.cs:41
public static readonly HranaValue Null = new() { Type = "null" };
public static HranaValue Encode(object? value)
{
switch (value)
{
case null or DBNull:
return Null;
case bool b:
return new HranaValue { Type = "integer", StringValue = b ? "1" : "0" };
case sbyte or byte or short or ushort or int or uint or long:
return new HranaValue { Type = "integer", StringValue = Convert.ToInt64(value, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture) };
case ulong ul:
return new HranaValue { Type = "integer", StringValue = ul.ToString(CultureInfo.InvariantCulture) };
case float f:
return double.IsFinite(f)
? new HranaValue { Type = "float", DoubleValue = f }
: throw new ArgumentException("Only finite numbers (not Infinity or NaN) can be passed as arguments");
case double d:
return double.IsFinite(d)
? new HranaValue { Type = "float", DoubleValue = d }
: throw new ArgumentException("Only finite numbers (not Infinity or NaN) can be passed as arguments");
case decimal m:
return new HranaValue { Type = "float", DoubleValue = (double)m };
case string s:
return new HranaValue { Type = "text", StringValue = s };
case char c:
return new HranaValue { Type = "text", StringValue = c.ToString() };
case Guid g:
return new HranaValue { Type = "text", StringValue = g.ToString() };
case DateTime dt:
return new HranaValue { Type = "text", StringValue = dt.ToString("o", CultureInfo.InvariantCulture) };
case DateTimeOffset dto:
return new HranaValue { Type = "text", StringValue = dto.ToString("o", CultureInfo.InvariantCulture) };
case byte[] bytes:
return new HranaValue { Type = "blob", BlobValue = bytes };View on GitHub (pinned to 244cde92a7)
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
Example fix
// before
float ratio = total / count; // 0/0 -> NaN
cmd.Parameters.AddWithValue("@r", ratio);
// after
float ratio = count == 0 ? 0f : total / count;
cmd.Parameters.AddWithValue("@r", ratio); Defensive patterns
Strategy: type-guard
Validate before calling
float SafeFloat(float v) => float.IsFinite(v) ? v : throw new ArgumentOutOfRangeException(nameof(v), "non-finite float");
Type guard
static bool IsBindableFloat(float value) => float.IsFinite(value);
Try / catch
try { cmd.Parameters.AddWithValue("@v", v); } catch (ArgumentException) when (v is float f && !float.IsFinite(f)) { cmd.Parameters.AddWithValue("@v", DBNull.Value); } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Unexpected token for last_insert_rowid: {reader.TokenType}
- Unsupported argument type: {value.GetType()}
- Describe execution failed
- Unexpected describe response
- SQL execution failed
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/a6475200ced79421.
Report an issue: GitHub.