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

  1. Only prepare SELECT and data-modification statements; execute DDL and other statements directly with session.execute()
  2. Refactor framework/ORM layers to whitelist statement types before calling prepare()
  3. 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

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


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)