apache/cassandra · error · InvalidRequestException
Invalid number of arguments, expecting
Error message
Invalid number of arguments, expecting %d values but got %d
What it means
StressCQLSSTableWriter.rawAddRow(List<ByteBuffer>) binds the provided values to the bound variables of the prepared INSERT statement. It throws InvalidRequestException when the number of supplied values does not exactly match the number of bind variables in the INSERT statement. The expected and actual counts are included in the message.
Solutions
- Count the '?' placeholders in your INSERT statement and match the list size exactly.
- Rebuild the values list from the table schema to ensure column order/count alignment.
- Add an assertion before the call comparing values.size() against the known bind count.
- Use the Map/Object[]-based addRow variants that bind by name instead of position.
Example fix
// before writer.rawAddRow(Arrays.asList(key, col1)); // INSERT has 3 bind variables // after writer.rawAddRow(Arrays.asList(key, col1, col2));
Defensive patterns
Strategy: validation
Validate before calling
// values built per row
List<ByteBuffer> values = buildRow();
if (values.size() != expectedBindCount) throw new IllegalArgumentException("expected " + expectedBindCount + " got " + values.size());
writer.rawAddRow(values); Try / catch
try { writer.rawAddRow(values); }
catch (InvalidRequestException e) {
// message contains expected vs actual counts; log the row for inspection
throw new IllegalArgumentException("row shape mismatch: " + e.getMessage(), e);
} Prevention
- Keep a constant for the bind-variable count next to the INSERT string.
- Derive values from the table schema, not hand-written lists.
- Prefer Map-based addRow to bind by column name.
- Update value-building code together with schema changes.
When it happens
Trigger: Calling rawAddRow(values) where values.size() != boundNames.size(), i.e. providing fewer or more ByteBuffers than the '?' placeholders in the using() INSERT statement.
Common situations: Schema changed (column added/removed) but the value-building code was not updated; accidentally passing a row with nulls omitted; off-by-one when concatenating key and column values.
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
- Cannot specify tokens without keyspace.
- Invalid number of arguments, expecting
- Key in . is invalid in
- No insert statement specified, you should provide an insert…
- No output directories specified, you should provide a…
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/f239eb02f9970fa5.
Report an issue: GitHub.
Appendix: source
Thrown at tools/stress/src/org/apache/cassandra/io/sstable/StressCQLSSTableWriter.java:259
throws InvalidRequestException, IOException
{
return rawAddRow(Arrays.asList(values));
}
/**
* Adds a new row to the writer given already serialized values.
* <p>
* This is a shortcut for {@code rawAddRow(Arrays.asList(values))}.
*
* @param values the row values (corresponding to the bind variables of the
* insertion statement used when creating by this writer) as binary.
* @return this writer.
*/
public StressCQLSSTableWriter rawAddRow(List<ByteBuffer> values)
throws InvalidRequestException, IOException
{
if (values.size() != boundNames.size())
throw new InvalidRequestException(String.format("Invalid number of arguments, expecting %d values but got %d", boundNames.size(), values.size()));
QueryOptions options = QueryOptions.forInternalCalls(null, values);
ClientState state = ClientState.forInternalCalls();
List<ByteBuffer> keys = insert.buildPartitionKeyNames(options, state);
SortedSet<Clustering<?>> clusterings = insert.createClustering(options, state);
long now = currentTimeMillis();
// Note that we asks indexes to not validate values (the last 'false' arg below) because that triggers a 'Keyspace.open'
// and that forces a lot of initialization that we don't want.
RowUpdateBuilder builder = new RegularRowUpdateBuilder(insert.metadata(),
ClientState.forInternalCalls(),
options,
insert.getTimestamp(TimeUnit.MILLISECONDS.toMicros(now), options),
(int) TimeUnit.MILLISECONDS.toSeconds(now),
insert.getTimeToLive(options),
null);
tryView on GitHub (pinned to 88fd0f6a0e)