apache/cassandra · error · InvalidRequestException

More than one restriction was found for the start bound on %

Error message

More than one restriction was found for the start bound on %s

What it means

Thrown when two restrictions both constrain the START bound of the same clustering slice — i.e. both operators are GT, GTE or BETWEEN on overlapping columns. A slice can have only one lower bound, so merging them is impossible and validation fails.

Source

Thrown at src/java/org/apache/cassandra/cql3/restrictions/MergedRestriction.java:162

        }

        if (restriction.isSlice() && other.isSlice())
        {
            ColumnMetadata firstColumn = restriction.firstColumn();
            ColumnMetadata otherFirstColumn = other.firstColumn();
            if (!firstColumn.equals(otherFirstColumn))
            {
                ColumnMetadata column = firstColumn.position() > otherFirstColumn.position() ? firstColumn
                                                                                             : otherFirstColumn;

                throw invalidRequest("Column \"%s\" cannot be restricted by two inequalities not starting with the same column",
                                     column.name);
            }

            if ((restriction.operator() == Operator.GT || restriction.operator() == Operator.GTE || restriction.operator() == Operator.BETWEEN) &&
                    (other.operator() == Operator.GT || other.operator() == Operator.GTE || other.operator() == Operator.BETWEEN))
            {
                throw invalidRequest("More than one restriction was found for the start bound on %s",
                                     toCQLString(getColumnsInCommons(restriction, other)));
            }

            if ((restriction.operator() == Operator.LT || restriction.operator() == Operator.LTE || restriction.operator() == Operator.BETWEEN) &&
                    (other.operator() == Operator.LT || other.operator() == Operator.LTE || other.operator() == Operator.BETWEEN))
            {
                throw invalidRequest("More than one restriction was found for the end bound on %s",
                                     toCQLString(getColumnsInCommons(restriction, other)));
            }
        }
    }

    private static void checkOperator(SimpleRestriction restriction)
    {
        if (restriction.isColumnLevel() || restriction.isOnToken())
        {
            if (restriction.isEQ())
                throw invalidRequest("%s cannot be restricted by more than one relation if it includes an Equal",

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Remove one of the duplicate lower-bound restrictions or make them consistent
  2. Express the tighter bound once using a single tuple (c1, c2) > (...) restriction
  3. Have the query builder merge/overwrite range predicates instead of appending both

Example fix

// before
SELECT * FROM t WHERE c1 > 1 AND (c1, c2) > (1, 5);
// after
SELECT * FROM t WHERE (c1, c2) > (1, 5);
Defensive patterns

Strategy: validation

Validate before calling

// deduplicate lower-bound predicates before building the query
const lower = predicates.filter(p => ['>','>='].includes(p.op));
if (lower.length > 1) throw new Error('Duplicate start bound on ' + lower.map(p => p.column));

Prevention

When it happens

Trigger: A SELECT with two lower-bound inequalities such as WHERE c1 > 1 AND (c1, c2) > (1, 2), or two > / >= / BETWEEN relations whose columns intersect, passed to MergedRestriction.validate().

Common situations: Combining a simple inequality with a multi-column (tuple) inequality over the same columns; hand-built queries from ORMs/query builders that append range predicates without deduplication.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


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