{"record":{"id":"4cd429ec6151d7d4","repo":"apache/cassandra","slug":"provided-preparedmodificationstatement-statement-h","errorCode":null,"errorMessage":"Provided preparedModificationStatement statement has no bind variables","messagePattern":"Provided preparedModificationStatement statement has no bind variables","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/io/sstable/CQLSSTableWriter.java","lineNumber":921,"sourceCode":"        }\n\n        /**\n         * Prepares modification statement for writing data to SSTable\n         *\n         * @return prepared modification statement and it's bound names\n         */\n        private ModificationStatement prepareModificationStatement()\n        {\n            ClientState state = ClientState.forInternalCalls();\n            ModificationStatement preparedModificationStatement = modificationStatement.prepare(state);\n            preparedModificationStatement.validate(state);\n\n            if (preparedModificationStatement.hasConditions())\n                throw new IllegalArgumentException(\"Conditional statements are not supported\");\n            if (preparedModificationStatement.isCounter())\n                throw new IllegalArgumentException(\"Counter modification statements are not supported\");\n            if (preparedModificationStatement.getBindVariables().isEmpty())\n                throw new IllegalArgumentException(\"Provided preparedModificationStatement statement has no bind variables\");\n\n            return preparedModificationStatement;\n        }\n    }\n}\n","sourceCodeStart":903,"sourceCodeEnd":927,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/sstable/CQLSSTableWriter.java#L903-L927","documentation":"CQLSSTableWriter exists to bind values into a prepared modification statement; a statement with zero bind variables cannot be batched/reused for bulk rows, so the Builder rejects it with an IllegalArgumentException. This is a usability guard that almost always indicates the statement was written with literal values instead of ? placeholders.","triggerScenarios":"Passing a fully literal statement like 'INSERT INTO ks.t (k, v) VALUES (1, 2)' (no ? markers) to CQLSSTableWriter and calling build().","commonSituations":"Hardcoded single-row loads; templating bugs where interpolation happened before preparation, leaving no placeholders.","solutions":["Rewrite the statement with ? placeholders for the values you will bind per row","If you truly need a one-off literal write, use a regular session.execute of the literal CQL instead of CQLSSTableWriter","Check any string templating that might have substituted values before the statement reached the builder"],"exampleFix":"// before\nString cql = \"INSERT INTO ks.t (k, v) VALUES (1, 2)\";\n// after\nString cql = \"INSERT INTO ks.t (k, v) VALUES (?, ?)\";\nwriter.addRow(1, 2);","handlingStrategy":"validation","validationCode":"if (!cql.contains(\"?\"))\n    throw new IllegalArgumentException(\"Statement must contain bind variables for CQLSSTableWriter\");","typeGuard":null,"tryCatchPattern":"try { builder.build(); }\ncatch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"has no bind variables\"))\n        // rewrite statement with ? placeholders\n}","preventionTips":["Always parameterize bulk-load statements with ? placeholders","Avoid templating that substitutes literals before preparation","Count expected bind markers against addRow arity"],"tags":["sstable","bulk-loading","bind-variables","invalid-argument"],"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-17T15:17:12.973Z"}