{"record":{"id":"a989efb628f9232f","repo":"apache/cassandra","slug":"there-were-d-markers-in-cql-but-d-bound-varia","errorCode":null,"errorMessage":"there were %d markers(?) in CQL but %d bound variables","messagePattern":"there were (.+?) markers\\(\\?\\) in CQL but (.+?) bound variables","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/QueryProcessor.java","lineNumber":916,"sourceCode":"    public ResultMessage processPrepared(CQLStatement statement,\n                                         QueryState state,\n                                         QueryOptions options,\n                                         Map<String, ByteBuffer> customPayload,\n                                         Dispatcher.RequestTime requestTime)\n                                                 throws RequestExecutionException, RequestValidationException\n    {\n        return processPrepared(statement, state, options, requestTime);\n    }\n\n    public ResultMessage processPrepared(CQLStatement statement, QueryState queryState, QueryOptions options, Dispatcher.RequestTime requestTime)\n    throws RequestExecutionException, RequestValidationException\n    {\n        int variablesSize = options.getValuesSize();\n        // Check to see if there are any bound variables to verify\n        if (!(variablesSize == 0 && statement.getBindVariables().isEmpty()))\n        {\n            if (variablesSize != statement.getBindVariables().size())\n                throw new InvalidRequestException(String.format(\"there were %d markers(?) in CQL but %d bound variables\",\n                                                                statement.getBindVariables().size(),\n                                                                variablesSize));\n\n            // at this point there is a match in count between markers and variables that is non-zero\n            if (logger.isTraceEnabled())\n                for (int i = 0; i < variablesSize; i++)\n                    logger.trace(\"[{}] '{}'\", i+1, options.getValues().get(i));\n        }\n\n        metrics.preparedStatementsExecuted.inc();\n        return processStatement(statement, queryState, options, requestTime);\n    }\n\n    public ResultMessage processBatch(BatchStatement statement,\n                                      QueryState state,\n                                      BatchQueryOptions options,\n                                      Map<String, ByteBuffer> customPayload,\n                                      Dispatcher.RequestTime requestTime)","sourceCodeStart":898,"sourceCodeEnd":934,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/QueryProcessor.java#L898-L934","documentation":"Before executing a prepared statement, Cassandra validates that the number of supplied bound values (from QueryOptions) equals the number of bind markers in the statement. A mismatch means the driver supplied the wrong number of variables, so execution is refused with InvalidRequestException.","triggerScenarios":"Executing a prepared statement (QueryProcessor.processStatement / executeInternal with QueryOptions) where options.getValuesSize() differs from statement.getBindVariables().size(); e.g. passing positional values to a named-marker statement, or reusing values from a modified query.","commonSituations":"Application code that caches the statement but builds the value list independently; driver/statement mismatch after a schema or query edit; hand-rolled native-protocol clients sending wrong value counts; executeInternal callers constructing QueryOptions manually.","solutions":["Count the '?' markers in the CQL string and supply exactly that many values in order","Re-prepare the statement if the query text changed since the values were built","Use the driver's bound statement API (bind) instead of manual positional arrays so counts are checked","Log statement.getBindVariables().size() vs supplied values to locate the off-by-N"],"exampleFix":"// before\nsession.execute(prepared.bind(v1, v2)); // statement has 3 markers\n// after\nBoundStatement bs = prepared.bind();\nbs.setString(\"c1\", v1).setInt(\"c2\", v2).setTimestamp(\"c3\", v3); // all 3 bound","handlingStrategy":"validation","validationCode":"if (values.size() != statement.getPreparedId().boundVariables().size())\n    throw new IllegalStateException(\"expected \" + statement.getPreparedId().boundVariables().size() + \" values, got \" + values.size());","typeGuard":null,"tryCatchPattern":"try { session.execute(prepared.bind(values)); } catch (InvalidRequestException e) { if (e.getMessage().contains(\"markers(?) in CQL but\")) rebuildValuesAndRetry(); else throw e; }","preventionTips":["Always bind values through the driver's BoundStatement API","Re-prepare statements after any query-text change","Keep value-list construction adjacent to the query string definition"],"tags":["cql","prepared-statement","bind-variables","arity-mismatch"],"backgroundTag":"missing-required-argument","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"}