apache/cassandra · error · InvalidRequestException

Expected elements in value for tuple , but got

Error message

Expected %d elements in value for tuple %s, but got %d: %s

What it means

Tuples.prepare checks that the number of elements in a tuple literal matches the receiver's TupleType arity. A literal with fewer or more elements than the tuple type declares is rejected with this error stating expected and actual counts.

Solutions

  1. Supply exactly tupleType.size() elements, using null for missing positions.
  2. Check the tuple arity via DESCRIBE TABLE and update the application's tuple construction.
  3. If records are variable length, pad/truncate in application code before building the literal.

Example fix

// before (tuple<int, text, double>)
INSERT INTO t (id, pos) VALUES (1, (1, 'x'));
// after
INSERT INTO t (id, pos) VALUES (1, (1, 'x', null));
Defensive patterns

Strategy: validation

Validate before calling

int arity = /* from system_schema.columns type tuple<...> */ 3;
if (values.length != arity) throw new IllegalArgumentException("expected " + arity + " tuple elements, got " + values.length);

Prevention

When it happens

Trigger: INSERT/UPDATE binding a tuple literal like (1, 'a') to a column of type tuple<int, text, double> (2 vs 3 elements), including frozen tuple literals and literal tuples in WHERE clauses during prepare.

Common situations: Schema altered the tuple arity (ALTER ... tuple type changed) while client literals were not updated; generating literals from variable-length records (CSV/JSON rows); positional destructuring mistakes.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/terms/Tuples.java:76

        public Literal(List<Term.Raw> elements)
        {
            this.elements = elements;
        }

        public Term prepare(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
        {
            // The parser cannot differentiate between a tuple with one element and a term between parenthesis.
            // By consequence, we need to wait until we know the target type to determine which one it is.
            if (elements.size() == 1 && !checkIfTupleType(receiver.type))
                return elements.get(0).prepare(keyspace, receiver);

            validateTupleAssignableTo(receiver, elements);

            TupleType tupleType = getTupleType(receiver.type);

            if (elements.size() != tupleType.size())
                throw invalidRequest("Expected %d elements in value for tuple %s, but got %d: %s",
                                     tupleType.size(), receiver.name, elements.size(), this);

            List<Term> values = new ArrayList<>(elements.size());
            boolean allTerminal = true;
            for (int i = 0; i < elements.size(); i++)
            {
                Term value = elements.get(i).prepare(keyspace, componentSpecOf(receiver, i));
                if (value instanceof Term.NonTerminal)
                    allTerminal = false;

                values.add(value);
            }

            MultiElements.DelayedValue value = new MultiElements.DelayedValue(tupleType, values);
            return allTerminal ? value.bind(FunctionContext.NONE) : value;
        }

        public TestResult testAssignment(String keyspace, ColumnSpecification receiver)

View on GitHub (pinned to 88fd0f6a0e)