tursodatabase/turso · error · InvalidOperationException

Missing value for parameter at position {i}.

Error message

Missing value for parameter at position {i}.

What it means

After the binding loop, Prepare() verifies that every placeholder from 1..parameterCount received a value (TursoCommand.cs:195-205). An unbound positional placeholder (written as ?) has no retrievable name, so GetParameterName returns null and the error reports the 1-based position: 'Missing value for parameter at position {i}.'.

Source

Thrown at bindings/dotnet/src/Turso.Data/TursoCommand.cs:208

                else
                {
                    var parameterIndex = i + 1;
                    if (parameterIndex > parameterCount)
                        throw new InvalidOperationException($"Parameter at position {parameterIndex} was not found in the SQL statement.");

                    TursoBindings.BindParameter(preparedStatement, parameterIndex, parameter.ToValue());
                    boundParameters[parameterIndex] = true;
                }
            }

            for (var i = 1; i <= parameterCount; i++)
            {
                if (!boundParameters[i])
                {
                    var parameterName = TursoBindings.GetParameterName(preparedStatement, i);
                    throw new InvalidOperationException(
                        parameterName is null
                            ? $"Missing value for parameter at position {i}."
                            : $"Missing value for parameter {parameterName}.");
                }
            }

            _statement?.Dispose();
            _statement = preparedStatement;
            preparedStatement = null;
        }
        finally
        {
            preparedStatement?.Dispose();
        }
    }

    protected override DbParameter CreateDbParameter()
    {
        return new TursoParameter();
    }

View on GitHub (pinned to c1e5928725)

Solutions

  1. Supply exactly one positional parameter per ? placeholder, in statement order.
  2. Validate placeholder count against Parameters.Count before executing (count '?' characters outside string literals).
  3. Switch to named placeholders (@id) so any missing value is reported by name instead of position.

Example fix

// before
cmd.CommandText = "SELECT * FROM t WHERE a = ? AND b = ?";
cmd.Parameters.AddWithValue(null, a); // b never supplied -> throws at position 2

// after
cmd.CommandText = "SELECT * FROM t WHERE a = ? AND b = ?";
cmd.Parameters.AddWithValue(null, a);
cmd.Parameters.AddWithValue(null, b);
Defensive patterns

Strategy: validation

Validate before calling

var placeholders = CountPlaceholders(cmd.CommandText); // count '?' outside string literals
var supplied = cmd.Parameters.Cast<TursoParameter>().Count(p => string.IsNullOrEmpty(p.ParameterName));
if (supplied < placeholders)
    throw new InvalidOperationException($"SQL needs {placeholders} positional values, got {supplied}.");

Try / catch

try
{
    cmd.Prepare();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Missing value for parameter at position"))
{
    // Parse the position from the message and add the missing value at that index.
}

Prevention

When it happens

Trigger: SQL "SELECT * FROM t WHERE a = ? AND b = ?" with only one nameless parameter supplied; a conditional code path that skips one of several AddWithValue calls.

Common situations: One forgotten parameter among many ? placeholders; an AddWithValue inside an if-branch that did not run; SQL gained a WHERE clause but the parameter list was not updated.

Related errors


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