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
An EXECUTE message references a prepared statement id that is not in this node's prepared-statement cache; handler.getPrepared(statementId) returned null so Cassandra throws PreparedQueryNotFoundException. The id was never prepared on this host, the host was restarted (in-memory cache lost), or the entry was evicted from the bounded cache.
Source
Thrown at src/java/org/apache/cassandra/transport/messages/ExecuteMessage.java:140
return true;
}
@Override
protected boolean isTrackable()
{
return true;
}
@Override
protected Message.Response execute(QueryState state, Dispatcher.RequestTime requestTime, boolean traceRequest)
{
QueryHandler.Prepared prepared = null;
try
{
QueryHandler handler = ClientState.getCQLQueryHandler();
prepared = handler.getPrepared(statementId);
if (prepared == null)
throw new PreparedQueryNotFoundException(statementId);
if (!prepared.fullyQualified && prepared.statement.eligibleAsPreparedStatement() && !Objects.equals(state.getClientState().getRawKeyspace(), prepared.keyspace))
{
state.getClientState().warnAboutUseWithPreparedStatements(statementId, prepared.keyspace);
String msg = String.format("Tried to execute a prepared unqualified statement on a keyspace it was not prepared on. " +
" Executing the resulting prepared statement will return unexpected results: %s (on keyspace %s, previously prepared on %s)",
statementId, state.getClientState().getRawKeyspace(), prepared.keyspace);
nospam.error(msg);
}
CQLStatement statement = prepared.statement;
options.prepare(statement.getBindVariables());
if (options.getPageSize() == 0)
throw new ProtocolException("The page size cannot be 0");
if (traceRequest)View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Re-issue PREPARE for the original CQL string and retry the execution (drivers do this transparently — keep the driver current)
- Enable the driver's reprepare-on-up/reconnect behavior so prepares are replayed after topology or restart events
- Do not persist or share prepared statement ids across sessions/restarts; treat them as ephemeral
- Reduce distinct prepared statement count if eviction pressure is high
Example fix
// before
session.execute(preparedId, values); // stale id after restart
// after
try {
session.execute(preparedId, values);
} catch (PreparedQueryNotFound e) {
PreparedStatement ps = session.prepare(cql);
session.execute(ps, values);
} Defensive patterns
Strategy: retry
Validate before calling
if (!session.getPreparedIds().contains(statementId)) {
PreparedStatement ps = session.prepare(cql);
statementId = ps.getPreparedId();
} Try / catch
try {
session.execute(preparedId, values);
} catch (PreparedQueryNotFoundException e) {
PreparedStatement ps = session.prepare(cql);
session.execute(ps.bind(values));
} Prevention
- Use a maintained driver that handles re-preparation transparently
- Enable reprepare-on-up for all contact points
- Treat prepared ids as ephemeral — no caching across restarts
- Monitor cache eviction metrics if preparing a very large number of distinct statements
When it happens
Trigger: Sending ExecuteMessage with a statementId not present in the QueryHandler cache — node restart, prepare sent to one node and execute routed to another, cache eviction under high statement cardinality, or client retaining ids from a previous cluster generation.
Common situations: Failover after a datacenter outage where clients resume with old ids; rolling upgrades/restarts evicting all prepared statements; applications storing prepared ids in persistent state; long-running workloads exceeding the prepared statement cache capacity.
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
- Prepared query with ID %s not found (either the query was no
- Value for a map addition has to be a map, but was: '%s'
- Invalid amount of bind variables
- Too many markers(?). %d markers exceed the allowed maximum o
- Prepared statement of size %d bytes is larger than allowed m
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/d7bcaa784228574c.
Report an issue: GitHub.