tursodatabase/turso · error · InvalidOperationException

ParameterName must be set.

Error message

ParameterName must be set.

What it means

This InvalidOperationException is thrown by ValidateManagedParameterValues when a SqliteParameter in the command's Parameters collection has an empty or null ParameterName. Managed Turso commands address parameters by name, so every parameter must have an explicit name before execution.

Source

Thrown at bindings/dotnet/src/Turso.Data.Sqlite/SqliteCommand.cs:527

        if (statement.FirstKeyword != "ROLLBACK")
            return false;

        var sql = statement.Sql.TrimStart();
        if (!sql.StartsWith("ROLLBACK", StringComparison.OrdinalIgnoreCase))
            return false;
        sql = sql["ROLLBACK".Length..].TrimStart();
        if (sql.StartsWith("TRANSACTION", StringComparison.OrdinalIgnoreCase))
            sql = sql["TRANSACTION".Length..].TrimStart();
        return sql.StartsWith("TO", StringComparison.OrdinalIgnoreCase);
    }

    internal void ValidateManagedParameterValues()
    {
        for (var index = 0; index < Parameters.Count; index++)
        {
            var parameter = Parameters[index];
            if (string.IsNullOrEmpty(parameter.ParameterName))
                throw new InvalidOperationException(Properties.Resources.RequiresSet(nameof(parameter.ParameterName)));
            if (!parameter.HasValue)
                throw new InvalidOperationException(Properties.Resources.RequiresSet(nameof(parameter.Value)));
        }
    }

    internal void AddManagedParameters(
        global::Turso.TursoCommand command,
        ManagedSqliteStatement statement)
    {
        var mapped = new Dictionary<string, SqliteParameter>(StringComparer.Ordinal);
        for (var index = 0; index < Parameters.Count; index++)
        {
            var parameter = Parameters[index];
            var parameterName = parameter.ParameterName;
            string? matchedName = null;
            if (statement.ParameterNames.Contains(parameterName, StringComparer.Ordinal))
            {
                matchedName = parameterName;

View on GitHub (pinned to 6c72522679)

Solutions

  1. Set ParameterName explicitly on each SqliteParameter before executing the command
  2. Use Named parameters in CommandText (e.g. @name) and add parameters with matching names via cmd.Parameters.AddWithValue("@name", value)
  3. Only use unnamed positional parameters on local (non-managed) connections

Example fix

// before
cmd.Parameters.Add(new SqliteParameter(42));

// after
cmd.Parameters.Add(new SqliteParameter("@id", 42));
Defensive patterns

Strategy: validation

Validate before calling

foreach (SqliteParameter p in cmd.Parameters)
    if (!p.HasValue)
        throw new InvalidOperationException($"Parameter '{p.ParameterName}' has no value.");

Type guard

bool HasValue(SqliteParameter p) => p.HasValue;

Try / catch

try { cmd.ExecuteNonQuery(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Value must be set"))
{
    // set missing Value or DBNull.Value and retry
}

Prevention

When it happens

Trigger: Adding SqliteParameter objects with only a Value (positional style, e.g. new SqliteParameter(value) or AddWithValue variants that leave the name empty) and then executing BuildBatch, PrepareManagedAsync, or ExecuteManagedAsync on a managed (direct remote / embedded replica) connection.

Common situations: Porting embedded SQLite code that used '?' positional parameters and unnamed parameter objects to managed Turso remote connections; copying parameters from another command where names were never assigned.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of tursodatabase/turso@6c72522679 (2026-09-06). Data as JSON: /api/errors/43790b1bdb780cd6. Report an issue: GitHub.