apache/cassandra · error · IllegalArgumentException
Invalid query, must be a %s statement but was: %s
Error message
Invalid query, must be a %s statement but was: %s
What it means
StressCQLSSTableWriter.parseStatement parses a CQL string with the ANTLR parser and then verifies that the resulting statement object is of the expected class (e.g. an INSERT for a writer opened as an insert writer, or DELETE/UPDATE for the corresponding variant). If the parsed statement is a different kind of statement, it throws IllegalArgumentException telling the caller what kind of statement was expected and what class was actually parsed. This guards the SSTable-writer API, which can only generate SSTables for the statement type it was constructed for.
Source
Thrown at tools/stress/src/org/apache/cassandra/io/sstable/StressCQLSSTableWriter.java:717
if (insert.hasConditions())
throw new IllegalArgumentException("Conditional statements are not supported");
if (insert.isCounter())
throw new IllegalArgumentException("Counter update statements are not supported");
if (insert.getBindVariables().isEmpty())
throw new IllegalArgumentException("Provided insert statement has no bind variables");
return insert;
}
}
public static <T extends CQLStatement.Raw> T parseStatement(String query, Class<T> klass, String type)
{
try
{
CQLStatement.Raw stmt = CQLFragmentParser.parseAnyUnhandled(CqlParser::query, query);
if (!stmt.getClass().equals(klass))
throw new IllegalArgumentException("Invalid query, must be a " + type + " statement but was: " + stmt.getClass());
return klass.cast(stmt);
}
catch (RecognitionException | RequestValidationException e)
{
throw new IllegalArgumentException(e.getMessage(), e);
}
}
}
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Make the CQL string passed to the writer match the writer kind: use an INSERT statement for an insert writer.
- Check that the statement does not start with a different keyword (SELECT/UPDATE/DELETE/BEGIN) and remove trailing semicolons or comments that could confuse classification.
- If you need a different statement type, build the writer with the matching factory (StressCQLSSTableWriter.builder for inserts vs the delete/update variants).
- Wrap the call in try/catch (IllegalArgumentException) and print the actual parsed statement class from the message to diagnose the mismatch.
Example fix
// before StressCQLSSTableWriter writer = StressCQLSSTableWriter.builder(schema, "UPDATE ks.t SET v = ? WHERE k = ?").build(); // after StressCQLSSTableWriter writer = StressCQLSSTableWriter.builder(schema, "INSERT INTO ks.t (k, v) VALUES (?, ?)").build();
Defensive patterns
Strategy: validation
Validate before calling
String cql = "INSERT INTO ks.t (k, v) VALUES (?, ?)";
String firstWord = cql.trim().split("\\s+", 2)[0].toUpperCase();
if (!firstWord.equals("INSERT"))
throw new IllegalArgumentException("Writer expects INSERT, got: " + firstWord); Type guard
boolean isInsert(Class<? extends CQLStatement.Raw> actual, Class<? extends CQLStatement.Raw> expected) {
return expected.equals(actual);
} Try / catch
try {
writer = StressCQLSSTableWriter.builder(schema, cql).build();
} catch (IllegalArgumentException e) {
throw new IllegalStateException("CQL does not match writer kind: " + e.getMessage(), e);
} Prevention
- Always generate the CQL string from the same constant used to select the writer kind.
- Strip trailing semicolons and comments before passing CQL to the builder.
- Unit-test writer construction for every profile statement type.
- Keep one factory method per statement type and never pass raw strings across kinds.
When it happens
Trigger: Calling StressCQLSSTableWriter.builder(...).build() for one operation kind (e.g. INSERT) and then passing a CQL string of a different kind (SELECT, UPDATE, DELETE) to the writer, so CQLFragmentParser.parseAnyUnhandled(CqlParser::query, query) returns a Raw statement whose class does not equal the expected klass.
Common situations: Copy-pasting a CQL statement of the wrong type into the writer builder; changing a schema string from INSERT to UPDATE (or adding options like IF NOT EXISTS) after configuring the writer; confusing compileOptions/insert vs update/delete writer factory methods in the stress tooling.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- %s
- category %s not found in %s
- GRANT operation is not supported by AllowAllAuthorizer
- REVOKE operation is not supported by AllowAllAuthorizer
- LIST PERMISSIONS operation is not supported by AllowAllAutho
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/3b5c8be738897849.
Report an issue: GitHub.