tursodatabase/turso · error · InvalidOperationException
Parameter at position {parameterIndex} was not found in the
Error message
Parameter at position {parameterIndex} was not found in the SQL statement. What it means
Positional (nameless) parameters are bound by collection order: the i-th parameter maps to placeholder index i+1 (TursoCommand.cs:184-188). If the collection holds more positional parameters than the statement has placeholders, i+1 exceeds GetParameterCount and Prepare throws InvalidOperationException reporting the offending position.
Source
Thrown at bindings/dotnet/src/Turso.Data/TursoCommand.cs:194
for (var i = 0; i < _parameterCollection.Count; i++)
{
var parameter = _parameterCollection[i] as TursoParameter;
if (parameter == null)
throw new ArgumentException("Parameter must be of type TursoParameter");
if (!string.IsNullOrEmpty(parameter.ParameterName))
{
var parameterIndex = TursoBindings.BindNamedParameter(preparedStatement, parameter.ParameterName, parameter.ToValue());
if (parameterIndex == 0)
throw new InvalidOperationException($"Parameter {parameter.ParameterName} was not found in the SQL statement.");
boundParameters[parameterIndex] = true;
}
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}.");
}
}
View on GitHub (pinned to c1e5928725)
Solutions
- Make the count of nameless parameters exactly equal the number of ? placeholders in the SQL.
- Call cmd.Parameters.Clear() before re-running a command with different SQL or parameter sets.
- Prefer named parameters when SQL is built dynamically so count/order drift cannot silently shift bindings.
Example fix
// before cmd.CommandText = "INSERT INTO t VALUES (?, ?)"; // 2 placeholders cmd.Parameters.AddWithValue(null, a); cmd.Parameters.AddWithValue(null, b); cmd.Parameters.AddWithValue(null, c); // 3rd positional -> throws at position 3 // after cmd.CommandText = "INSERT INTO t VALUES (?, ?)"; cmd.Parameters.AddWithValue(null, a); cmd.Parameters.AddWithValue(null, b);
Defensive patterns
Strategy: validation
Validate before calling
var positional = cmd.Parameters.Cast<TursoParameter>().Count(p => string.IsNullOrEmpty(p.ParameterName));
var placeholders = CountPlaceholders(cmd.CommandText); // count '?' outside string literals
if (positional > placeholders)
throw new InvalidOperationException($"{positional} positional parameters but only {placeholders} '?' placeholders."); Prevention
- Add exactly one nameless parameter per ? placeholder, in order.
- Call cmd.Parameters.Clear() before re-running a command with new SQL.
- Prefer named parameters for dynamically built SQL.
When it happens
Trigger: SQL "INSERT INTO t VALUES (?, ?)" with three nameless parameters added to Parameters; a loop that appends positional parameters without matching the placeholder count.
Common situations: Parameters added in a loop over a list whose length drifted from the SQL; a reused command object carrying leftover positional parameters; dynamic SQL that dropped a placeholder during editing.
Related errors
- Missing value for parameter at position {i}.
- Parameter must be of type TursoParameter
- Parameter {parameter.ParameterName} was not found in the SQL
- Missing value for parameter {parameterName}.
- Turso batch execution is currently supported only for remote
AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-20).
Data as JSON: /api/errors/cdeaf284214036fd.
Report an issue: GitHub.