tursodatabase/turso · error · InvalidCastException

Cannot convert remote null value to String.

Error message

Cannot convert remote null value to String.

What it means

TursoRemoteDataReader.GetString converts every non-null value to a string (via IFormattable with invariant culture) but maps DBNull to an explicit InvalidCastException, mirroring strict ADO.NET getter semantics where a null cannot become a string reference. Only null cells take this path; integers, doubles, and blobs are stringified instead.

Source

Thrown at bindings/dotnet/src/Turso.Data/TursoRemoteDataReader.cs:179

    public override int GetOrdinal(string name)
    {
        for (var i = 0; i < FieldCount; i++)
        {
            if (GetName(i) == name)
                return i;
        }

        throw new IndexOutOfRangeException($"column {name} not found");
    }

    public override string GetString(int ordinal)
    {
        var value = CurrentValue(ordinal).ToClrValue();
        return value switch
        {
            string text => text,
            DBNull => throw new InvalidCastException("Cannot convert remote null value to String."),
            IFormattable formattable => formattable.ToString(null, CultureInfo.InvariantCulture),
            _ => value.ToString() ?? string.Empty,
        };
    }

    public override object GetValue(int ordinal)
    {
        return CurrentValue(ordinal).ToClrValue();
    }

    public override int GetValues(object[] values)
    {
        ArgumentNullException.ThrowIfNull(values);

        var count = Math.Min(values.Length, FieldCount);
        for (var i = 0; i < count; i++)
            values[i] = GetValue(i);

View on GitHub (pinned to 6c72522679)

Solutions

  1. Check reader.IsDBNull(ordinal) before calling GetString and decide on a fallback (empty string, null variable, or sentinel).
  2. Use GetValue(ordinal) and convert with Convert.ToString(...) or an `as string` pattern when the column may be null.
  3. Fix the query with COALESCE(col, '') when an empty string is an acceptable representation.
  4. For typed materialization, map the column to a nullable CLR type (string? handles DBNull via GetValue + cast).

Example fix

// before
string title = reader.GetString(1); // NULL cell -> InvalidCastException

// after
string title = reader.IsDBNull(1) ? string.Empty : reader.GetString(1);
Defensive patterns

Strategy: type-guard

Validate before calling

// GetString is only safe on non-null cells
if (!reader.IsDBNull(ordinal))
    var text = reader.GetString(ordinal);

Type guard

static string GetStringOrNull(DbDataReader r, int i) => r.IsDBNull(i) ? null : r.GetString(i);

Try / catch

try { s = reader.GetString(i); }
catch (InvalidCastException) when (reader.IsDBNull(i)) { s = null; }

Prevention

When it happens

Trigger: Calling GetString(ordinal) when the current row's cell is SQL NULL: a nullable TEXT column with no value, the right side of a LEFT JOIN that did not match, or an aggregate like MAX over an empty set.

Common situations: Optional fields (middle name, description) that are null for some rows; LEFT JOIN detail rows; columns defaulted to NULL; code ported from a driver that returned null or empty string for NULL.

Related errors


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