tursodatabase/turso · error · InvalidCastException

Cannot convert remote {Type} value to Double.

Error message

Cannot convert remote {Type} value to Double.

What it means

GetDouble on a reader column whose remote value type is not float, integer, or text. NULL and BLOB values have no conversion arm, so a NULL cell read with GetDouble throws InvalidCastException rather than yielding a default.

Source

Thrown at bindings/dotnet/src/Turso.Data/TursoRemoteClient.cs:687

    public long GetInt64()
    {
        return Type switch
        {
            "integer" => ParseInteger(),
            "float" => checked((long)ParseFloat()),
            "text" => long.Parse(Value.GetString() ?? "", CultureInfo.InvariantCulture),
            _ => throw new InvalidCastException($"Cannot convert remote {Type} value to Int64."),
        };
    }

    public double GetDouble()
    {
        return Type switch
        {
            "float" => ParseFloat(),
            "integer" => ParseInteger(),
            "text" => double.Parse(Value.GetString() ?? "", CultureInfo.InvariantCulture),
            _ => throw new InvalidCastException($"Cannot convert remote {Type} value to Double."),
        };
    }

    public decimal GetDecimal()
    {
        return Type switch
        {
            "float" => Convert.ToDecimal(ParseFloat(), CultureInfo.InvariantCulture),
            "integer" => ParseInteger(),
            "text" => decimal.Parse(Value.GetString() ?? "", CultureInfo.InvariantCulture),
            _ => throw new InvalidCastException($"Cannot convert remote {Type} value to Decimal."),
        };
    }

    private long ParseInteger()
    {
        return Value.ValueKind == JsonValueKind.String
            ? long.Parse(Value.GetString() ?? "", CultureInfo.InvariantCulture)

View on GitHub (pinned to 6c72522679)

Solutions

  1. Guard with reader.IsDBNull(i) before GetDouble and substitute 0.0 or double.NaN as appropriate.
  2. Use COALESCE/IFNULL in the SQL so the server never returns NULL for that column.
  3. Verify the column ordinal and underlying type before switching to typed getters.
  4. For text columns that should be numeric, parse manually with double.TryParse to control the failure mode.

Example fix

// before
double avg = reader.GetDouble(0);

// after
double avg = reader.IsDBNull(0) ? 0.0 : reader.GetDouble(0);
Defensive patterns

Strategy: validation

Validate before calling

if (reader.IsDBNull(ordinal))
    return 0.0; // or double.NaN as your domain sentinel
return reader.GetDouble(ordinal);

Type guard

static bool CanReadDouble(System.Data.Common.DbDataReader reader, int i) =>
    !reader.IsDBNull(i)
    && reader.GetFieldType(i) is Type t
    && (t == typeof(double) || t == typeof(long) || t == typeof(string));

Try / catch

try { value = reader.GetDouble(i); }
catch (InvalidCastException) when (reader.IsDBNull(i))
{
    value = 0.0;
}

Prevention

When it happens

Trigger: reader.GetDouble(i) on a remote connection where column i is NULL, a BLOB, or an unsupported type; numeric-looking text goes through double.Parse, which throws FormatException for non-numeric strings instead.

Common situations: Aggregates returning NULL on empty sets (AVG over zero rows); nullable REAL columns read without null checks; schema drift turning a REAL column into TEXT or BLOB.

Related errors


AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-08-20). Data as JSON: /api/errors/27239c17405f5348. Report an issue: GitHub.