tursodatabase/turso · error · InvalidCastException

Cannot convert remote {Type} value to Int64.

Error message

Cannot convert remote {Type} value to Int64.

What it means

GetInt64 on a reader column whose remote value type is not integer, float, or text. The switch has no arms for null or blob, so calling GetInt64 on a NULL column or a BLOB column throws InvalidCastException -- the remote protocol distinguishes NULL as its own type, and the typed getter refuses to invent a value for it.

Source

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

        return Type switch
        {
            "null" => DBNull.Value,
            "integer" => ParseInteger(),
            "float" => ParseFloat(),
            "text" => Value.GetString() ?? string.Empty,
            "blob" => DecodeBase64(Base64 ?? string.Empty),
            _ => throw new TursoException($"Remote response returned unsupported value type: {Type}"),
        };
    }

    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
        {

View on GitHub (pinned to 6c72522679)

Solutions

  1. Check reader.IsDBNull(i) before GetInt64 and decide on a default (0, or skip the row).
  2. Verify the column ordinal maps to the column you expect -- misaligned ordinals are a classic cause.
  3. If the column can legitimately hold non-numeric text or blobs, read it as GetValue and convert explicitly.
  4. Confirm the schema with a raw SELECT and adjust the query to COALESCE the column when a default is acceptable.

Example fix

// before
long id = reader.GetInt64(0);

// after
long id = reader.IsDBNull(0) ? 0L : reader.GetInt64(0);
Defensive patterns

Strategy: validation

Validate before calling

if (reader.IsDBNull(ordinal))
    return 0L; // or your domain default for NULL
return reader.GetInt64(ordinal);

Type guard

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

Try / catch

try { value = reader.GetInt64(i); }
catch (InvalidCastException) when (reader.IsDBNull(i))
{
    value = 0L; // NULL column: choose an explicit domain default
}

Prevention

When it happens

Trigger: reader.GetInt64(i) on a remote connection where column i is NULL (most common), a BLOB, or an unsupported type. Text values take a long.Parse path, so non-numeric text instead throws FormatException.

Common situations: Nullable columns (COUNT(*)-style absent rows, LEFT JOIN misses, optional fields) read without an IsDBNull check; schema changes making a column nullable after code shipped; BLOB columns read with numeric getters.

Related errors


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