apache/cassandra · error · InvalidRequestException
Cannot provide custom timestamp for conditional BATCH
Error message
Cannot provide custom timestamp for conditional BATCH
What it means
A batch that contains conditional statements (LWT, e.g. IF NOT EXISTS / IF condition) cannot also carry a batch-level custom timestamp USING TIMESTAMP, because condition evaluation determines the write timestamp. BatchStatement.validate() throws this InvalidRequestException.
Source
Thrown at src/java/org/apache/cassandra/cql3/statements/BatchStatement.java:262
@Override
public void authorize(ClientState state) throws InvalidRequestException, UnauthorizedException
{
ModificationStatement.TableAuthorizationState authorizationState = new ModificationStatement.TableAuthorizationState();
for (ModificationStatement statement : statements)
statement.authorize(state, authorizationState);
}
// Validates a prepared batch statement without validating its nested statements.
public void validate() throws InvalidRequestException
{
if (attrs.isTimeToLiveSet())
throw new InvalidRequestException("Global TTL on the BATCH statement is not supported.");
boolean timestampSet = attrs.isTimestampSet();
if (timestampSet)
{
if (hasConditions)
throw new InvalidRequestException("Cannot provide custom timestamp for conditional BATCH");
if (isCounter())
throw new InvalidRequestException("Cannot provide custom timestamp for counter BATCH");
}
boolean hasCounters = false;
boolean hasNonCounters = false;
boolean hasVirtualTables = false;
boolean hasRegularTables = false;
for (ModificationStatement statement : statements)
{
if (timestampSet && statement.isTimestampSet())
throw new InvalidRequestException("Timestamp must be set either on BATCH or individual statements: " + statement.source);
if (statement.isCounter())
hasCounters = true;View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Remove USING TIMESTAMP from the conditional batch
- Move the conditional statements to a separate batch without a custom timestamp
- Use per-statement timestamps only on non-conditional statements in a different batch
Example fix
// before BEGIN BATCH USING TIMESTAMP 1234 INSERT INTO t ... IF NOT EXISTS; APPLY BATCH; // after BEGIN BATCH INSERT INTO t ... IF NOT EXISTS; APPLY BATCH; // no USING TIMESTAMP
Defensive patterns
Strategy: validation
Validate before calling
boolean hasConditions = statements.stream().anyMatch(s -> s.hasConditions());
if (hasConditions && batchUsesTimestamp) throw new IllegalArgumentException("drop USING TIMESTAMP for conditional batches"); Try / catch
try { session.execute(batch); }
catch (InvalidQueryException e) {
if (e.getMessage().contains("custom timestamp for conditional BATCH")) { /* remove USING TIMESTAMP */ }
} Prevention
- Never combine USING TIMESTAMP with IF EXISTS / IF NOT EXISTS / IF conditions in batches
- Keep LWT batches separate from timestamp-controlled write batches
When it happens
Trigger: BEGIN BATCH ... USING TIMESTAMP 12345 ... containing any statement with conditions (hasConditions), executed directly or via prepare.
Common situations: Combining compare-and-set workflows with explicit timestamps; query builders that always append USING TIMESTAMP.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Conditional BATCH statements cannot include mutations for vi
- Batch with conditions cannot span multiple tables: %s
- Invalid empty serial consistency level
- Batch with conditions cannot span multiple partitions
- Global TTL on the BATCH statement is not supported.
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/63ceb09a272b9f2a.
Report an issue: GitHub.