apache/cassandra · error · PreparedQueryNotFoundException

Prepared query with ID %s not found (either the query was no

Error message

Prepared query with ID %s not found (either the query was not prepared on this host (maybe the host has been restarted?) or you have prepared too many queries and it has been evicted from the internal cache)

What it means

The batch references a prepared statement by MD5 id that is absent from this node's prepared-statement cache (QueryHandler.getPrepared returned null). Cassandra throws PreparedQueryNotFoundException: the query was never prepared on this host, the host restarted and lost its cache, or the entry was evicted because the cache is full.

Source

Thrown at src/java/org/apache/cassandra/transport/messages/BatchMessage.java:197

                traceQuery(state);

            QueryHandler handler = ClientState.getCQLQueryHandler();
            prepared = new ArrayList<>(queryOrIdList.size());
            for (int i = 0; i < queryOrIdList.size(); i++)
            {
                Object query = queryOrIdList.get(i);
                QueryHandler.Prepared p;
                if (query instanceof String)
                {
                    p = QueryProcessor.parseAndPrepare((String) query,
                                                       state.getClientState().cloneWithKeyspaceIfSet(options.getKeyspace()),
                                                       false, false);
                }
                else
                {
                    p = handler.getPrepared((MD5Digest)query);
                    if (null == p)
                        throw new PreparedQueryNotFoundException((MD5Digest)query);
                }

                byte[][] queryValues = values.get(i);
                if (queryValues.length != p.statement.getBindVariables().size())
                    throw new InvalidRequestException(String.format("There were %d markers(?) in CQL but %d bound variables",
                                                                    p.statement.getBindVariables().size(),
                                                                    queryValues.length));

                prepared.add(p);
            }

            BatchQueryOptions batchOptions = BatchQueryOptions.withPerStatementVariables(options, values, queryOrIdList);
            List<ModificationStatement> statements = new ArrayList<>(prepared.size());
            List<String> queries = QueryEvents.instance.hasListeners() ? new ArrayList<>(prepared.size()) : null;
            for (int i = 0; i < prepared.size(); i++)
            {
                CQLStatement statement = prepared.get(i).statement;
                if (queries != null)

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Catch the error, re-issue PREPARE for the statement, then re-send the batch (modern drivers do this automatically)
  2. Make sure the driver's load-balancing/reprepare-on-up logic is enabled so prepares are replayed on all hosts
  3. Avoid caching prepared ids in the application across reconnects; fetch fresh ids from the driver
  4. If evictions are frequent, review workload cardinality — thousands of distinct prepared statements churn the cache

Example fix

// before
session.executeBatch(batchWithStaleIds);
// after
try {
    session.executeBatch(batch);
} catch (PreparedQueryNotFound e) {
    PreparedStatement ps = session.prepare(originalCql); // re-prepare
    session.executeBatch(batchWith(ps));
}
Defensive patterns

Strategy: retry

Validate before calling

// Cannot validate remotely; ensure ids come from the live session:
if (!session.isPrepared(preparedId))
    preparedId = session.prepare(cql).getPreparedId();

Try / catch

try {
    session.executeBatch(batch);
} catch (PreparedQueryNotFoundException e) {
    PreparedStatement ps = session.prepare(e.getQueryString());
    session.executeBatch(rebind(batch, ps));
}

Prevention

When it happens

Trigger: Sending a BatchMessage with a query id from handler.getPrepared((MD5Digest)query) == null — typically after a node restart, failover to a node that never saw the prepare, or eviction of the least-recently-used prepared statement.

Common situations: Client keeps prepared ids across a server restart; load balancer routes the batch to a different node than the PREPARE went to; heavy workload evicts entries faster than the client refreshes; driver reconnection logic reuses stale ids.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/8e10f68a449bce28. Report an issue: GitHub.