apache/cassandra · info · ClientWarn
Prepared statements for other than modification and…
Error message
Prepared statements for other than modification and selection statements should be avoided, statement id: %s
What it means
A client warning emitted when a statement other than a modification (INSERT/UPDATE/DELETE) or selection (SELECT) statement — e.g. schema statements like CREATE TABLE or USE — is prepared. Preparing such statements provides no benefit and may cause ambiguity; it is warned once per session.
Solutions
- Only prepare SELECT and data-modification statements; execute DDL and other statements directly with session.execute()
- Refactor framework/ORM layers to whitelist statement types before calling prepare()
- Acknowledge the warning is client-visible only (ClientWarn); no server-side action is taken, but remove the pattern
Example fix
// before
PreparedStatement ps = session.prepare("CREATE TABLE myks.t (id int PRIMARY KEY)");
session.execute(ps.bind());
// after
session.execute("CREATE TABLE myks.t (id int PRIMARY KEY)"); Defensive patterns
Strategy: validation
Validate before calling
// only prepare SELECT / modification statements
String verb = statement.trim().split("\\s+")[0].toLowerCase();
if (!(verb.equals("select") || verb.equals("insert") || verb.equals("update") || verb.equals("delete") || verb.equals("batch")))
throw new IllegalArgumentException("Do not prepare '" + verb + "' statements; execute them directly"); Try / catch
// driver-side warning handler to surface the misuse
cluster.register(warnings -> warnings.forEach(w -> log.warn("Server warning: {}", w))); Prevention
- Execute DDL (CREATE/ALTER/DROP) directly with session.execute, never prepare()
- Whitelist preparable statement verbs in ORM/templating layers
- Enable driver warning handlers to catch this in dev/test
When it happens
Trigger: A client sends a PREPARE message whose statement parses to something other than a modification or selection statement, e.g. `PREPARE CREATE TABLE ...` / prepared ALTER/USE statements via the driver's session.prepare().
Common situations: Drivers/frameworks that blindly call session.prepare() on every CQL string including DDL; migration tools that pre-prepare schema scripts; templated query layers preparing utility statements.
Understand the failure class
Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.
Related errors
- ACCESS TO DATACENTERS operations not supported by…
- Altering column types is no longer supported
- Bind variables are not allowed in CREATE MATERIALIZED VIEW…
- Cannot add a counter column to Accord table
- Cannot add new column to a COMPACT STORAGE table
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/5ae222868339cdd6.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/service/ClientState.java:728
}
public void warnAboutUseWithPreparedStatements(MD5Digest statementId, String preparedKeyspace)
{
if (!issuedPreparedStatementsUseWarning)
{
ClientWarn.instance.warn(String.format("`USE <keyspace>` with prepared statements is considered to be an anti-pattern due to ambiguity in non-qualified table names. " +
"Please consider removing instances of `Session#setKeyspace(<keyspace>)`, `Session#execute(\"USE <keyspace>\")` and `cluster.newSession(<keyspace>)` from your code, and " +
"always use fully qualified table names (e.g. <keyspace>.<table>). " +
"Keyspace used: %s, statement keyspace: %s, statement id: %s", getRawKeyspace(), preparedKeyspace, statementId));
issuedPreparedStatementsUseWarning = true;
}
}
public void warnAboutUneligiblePreparedStatement(MD5Digest statementId)
{
if (!issuedWarningForUneligiblePreparedStatements)
{
ClientWarn.instance.warn(String.format("Prepared statements for other than modification and selection statements should be avoided, statement id: %s", statementId));
issuedWarningForUneligiblePreparedStatements = true;
}
}
private static void validateKeyspace(String keyspace)
{
if (keyspace == null)
throw new InvalidRequestException("You have not set a keyspace for this session");
}
public AuthenticatedUser getUser()
{
return user;
}
private Set<Permission> authorize(IResource resource)
{
return user.getPermissions(resource);View on GitHub (pinned to 88fd0f6a0e)