apache/cassandra · error · InvalidRequestException

Too many markers(?). %d markers exceed the allowed maximum o

Error message

Too many markers(?). %d markers exceed the allowed maximum of %d

What it means

Cassandra limits the number of bind markers (?) in a single prepared statement to 65535 (MAX_UNSIGNED_SHORT), because bound variable indexes are encoded as unsigned shorts in the native protocol. When prepare() counts more bound terms than this limit it refuses to prepare the statement with InvalidRequestException.

Source

Thrown at src/java/org/apache/cassandra/cql3/QueryProcessor.java:815

                if (clientState.getRawKeyspace() != null && !cachedWithKeyspace.fullyQualified) // For non-fully qualified statements, we always include keyspace to avoid ambiguity
                    return createResultMessage(hashWithKeyspace, cachedWithKeyspace);

            }
            else // legacy caches, pre-CASSANDRA-15252 behaviour
            {
                return createResultMessage(hashWithKeyspace, cachedWithKeyspace);
            }
        }
        Prepared prepared = parseAndPrepare(queryString, clientState, false);
        CQLStatement statement = prepared.statement;

        if (!statement.eligibleAsPreparedStatement())
            clientState.warnAboutUneligiblePreparedStatement(hashWithKeyspace);

        int boundTerms = statement.getBindVariables().size();
        if (boundTerms > FBUtilities.MAX_UNSIGNED_SHORT)
            throw new InvalidRequestException(String.format("Too many markers(?). %d markers exceed the allowed maximum of %d", boundTerms, FBUtilities.MAX_UNSIGNED_SHORT));

        if (prepared.fullyQualified)
        {
            ResultMessage.Prepared qualifiedWithoutKeyspace = storePreparedStatement(queryString, null, prepared);
            ResultMessage.Prepared qualifiedWithKeyspace = null;
            if (clientState.getRawKeyspace() != null)
                qualifiedWithKeyspace = storePreparedStatement(queryString, clientState.getRawKeyspace(), prepared);

            if (!useNewPreparedStatementBehaviour && qualifiedWithKeyspace != null)
                return qualifiedWithKeyspace;

            return qualifiedWithoutKeyspace;
        }
        else
        {
            if (prepared.statement.eligibleAsPreparedStatement())
                clientState.warnAboutUseWithPreparedStatements(hashWithKeyspace, clientState.getRawKeyspace());

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Reduce the number of bind markers by splitting the statement into multiple smaller statements or batches
  2. Use literal values instead of bind markers for some columns
  3. If inserting many rows, execute multiple INSERT statements instead of one giant statement
  4. Verify column count; wide denormalized tables may need remodeling (e.g. clustering rows instead of many columns)

Example fix

// before
String stmt = "INSERT INTO t (k,c1,c2,...) VALUES (?,?,?,...)"; // 70000 markers
// after
for (List<Object> row : rows) session.execute("INSERT INTO t (...) VALUES (?,...)", row); // one statement per row
Defensive patterns

Strategy: validation

Validate before calling

int markers = countBindMarkers(cql); // count '?' outside string/quoted literals
if (markers > 65535) throw new IllegalArgumentException("Statement has " + markers + " markers; split it");

Try / catch

try { session.prepare(cql); } catch (InvalidRequestException e) { if (e.getMessage().contains("Too many markers")) splitAndRetry(cql); else throw e; }

Prevention

When it happens

Trigger: Calling prepare() (via session.prepare or QueryProcessor.prepare) on a CQL statement containing more than 65535 '?' bind markers, typically a very large INSERT/UPDATE or batch built programmatically.

Common situations: Code generators or ORMs that create one marker per column across thousands of columns; batch statements assembled in a loop without checking marker count; migration scripts converting rows into parameterized inserts.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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