{"record":{"id":"8e10f68a449bce28","repo":"apache/cassandra","slug":"prepared-query-with-id-s-not-found-either-the-qu","errorCode":null,"errorMessage":"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)","messagePattern":"Prepared query with ID (.+?) 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\\)","errorType":"exception","errorClass":"PreparedQueryNotFoundException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/transport/messages/BatchMessage.java","lineNumber":197,"sourceCode":"                traceQuery(state);\n\n            QueryHandler handler = ClientState.getCQLQueryHandler();\n            prepared = new ArrayList<>(queryOrIdList.size());\n            for (int i = 0; i < queryOrIdList.size(); i++)\n            {\n                Object query = queryOrIdList.get(i);\n                QueryHandler.Prepared p;\n                if (query instanceof String)\n                {\n                    p = QueryProcessor.parseAndPrepare((String) query,\n                                                       state.getClientState().cloneWithKeyspaceIfSet(options.getKeyspace()),\n                                                       false, false);\n                }\n                else\n                {\n                    p = handler.getPrepared((MD5Digest)query);\n                    if (null == p)\n                        throw new PreparedQueryNotFoundException((MD5Digest)query);\n                }\n\n                byte[][] queryValues = values.get(i);\n                if (queryValues.length != p.statement.getBindVariables().size())\n                    throw new InvalidRequestException(String.format(\"There were %d markers(?) in CQL but %d bound variables\",\n                                                                    p.statement.getBindVariables().size(),\n                                                                    queryValues.length));\n\n                prepared.add(p);\n            }\n\n            BatchQueryOptions batchOptions = BatchQueryOptions.withPerStatementVariables(options, values, queryOrIdList);\n            List<ModificationStatement> statements = new ArrayList<>(prepared.size());\n            List<String> queries = QueryEvents.instance.hasListeners() ? new ArrayList<>(prepared.size()) : null;\n            for (int i = 0; i < prepared.size(); i++)\n            {\n                CQLStatement statement = prepared.get(i).statement;\n                if (queries != null)","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/transport/messages/BatchMessage.java#L179-L215","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Catch the error, re-issue PREPARE for the statement, then re-send the batch (modern drivers do this automatically)","Make sure the driver's load-balancing/reprepare-on-up logic is enabled so prepares are replayed on all hosts","Avoid caching prepared ids in the application across reconnects; fetch fresh ids from the driver","If evictions are frequent, review workload cardinality — thousands of distinct prepared statements churn the cache"],"exampleFix":"// before\nsession.executeBatch(batchWithStaleIds);\n// after\ntry {\n    session.executeBatch(batch);\n} catch (PreparedQueryNotFound e) {\n    PreparedStatement ps = session.prepare(originalCql); // re-prepare\n    session.executeBatch(batchWith(ps));\n}","handlingStrategy":"retry","validationCode":"// Cannot validate remotely; ensure ids come from the live session:\nif (!session.isPrepared(preparedId))\n    preparedId = session.prepare(cql).getPreparedId();","typeGuard":null,"tryCatchPattern":"try {\n    session.executeBatch(batch);\n} catch (PreparedQueryNotFoundException e) {\n    PreparedStatement ps = session.prepare(e.getQueryString());\n    session.executeBatch(rebind(batch, ps));\n}","preventionTips":["Keep drivers current — modern drivers auto-reprepare on this error","Enable reprepare-on-up and reprepare-on-reconnect in driver config","Never persist prepared ids across restarts or sessions","Spread prepares across nodes if using a custom load balancing policy"],"tags":["cql","batch","prepared-statement","cache-miss","restart"],"backgroundTag":"resource-not-found","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}