apache/cassandra · error · IllegalArgumentException

Provided insert statement has no bind variables

Error message

Provided insert statement has no bind variables

What it means

For offline SSTable writing, every value must be bound at runtime via rawAddRow. prepareInsert() throws IllegalArgumentException when the parsed statement has no bind variables at all, because there would be nothing to bind per row and the writer cannot compute partition keys or clustings.

Solutions

  1. Replace literal values in the INSERT with '?' bind variables.
  2. Pass actual row values per record via rawAddRow(Object[]/List/Map) instead of baking them into the CQL string.
  3. Verify getBindVariables() is non-empty conceptually: one '?' per column in the INSERT.
  4. For one-off static rows, still parameterize and bind once.

Example fix

// before
builder.using("INSERT INTO ks.tbl (k, v) VALUES ('a', 1)");
// after
builder.using("INSERT INTO ks.tbl (k, v) VALUES (?, ?)");
writer.rawAddRow("a", 1);
Defensive patterns

Strategy: validation

Validate before calling

String cql = insertStmt;
int placeholders = cql.length() - cql.replace("?", "").length();
if (placeholders == 0) throw new IllegalArgumentException("INSERT must contain ? bind variables");

Try / catch

try { writer = builder.build(); }
catch (IllegalArgumentException e) { throw new IllegalStateException("parameterize the insert statement: " + e.getMessage(), e); }

Prevention

When it happens

Trigger: Passing a fully literal INSERT (no '?' placeholders) such as INSERT INTO ks.tbl (k, v) VALUES ('a', 1) to using(...).

Common situations: Hard-coded sample data inserted as a literal string; template generation code that inlined values instead of parameters; misunderstanding that rawAddRow values map to bound variables.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at tools/stress/src/org/apache/cassandra/io/sstable/StressCQLSSTableWriter.java:704

        /**
         * Prepares insert statement for writing data to SSTable
         *
         * @return prepared Insert statement and it's bound names
         */
        private UpdateStatement prepareInsert()
        {
            ClientState state = ClientState.forInternalCalls();
            CQLStatement cqlStatement = insertStatement.prepare(state);
            UpdateStatement insert = (UpdateStatement) cqlStatement;
            insert.validate(state);

            if (insert.hasConditions())
                throw new IllegalArgumentException("Conditional statements are not supported");
            if (insert.isCounter())
                throw new IllegalArgumentException("Counter update statements are not supported");
            if (insert.getBindVariables().isEmpty())
                throw new IllegalArgumentException("Provided insert statement has no bind variables");

            return insert;
        }
    }

    public static <T extends CQLStatement.Raw> T parseStatement(String query, Class<T> klass, String type)
    {
        try
        {
            CQLStatement.Raw stmt = CQLFragmentParser.parseAnyUnhandled(CqlParser::query, query);

            if (!stmt.getClass().equals(klass))
                throw new IllegalArgumentException("Invalid query, must be a " + type + " statement but was: " + stmt.getClass());

            return klass.cast(stmt);
        }
        catch (RecognitionException | RequestValidationException e)
        {

View on GitHub (pinned to 88fd0f6a0e)