apache/cassandra · error · InvalidRequestException

Multiple PRIMARY KEY specified for table

Error message

Multiple PRIMARY KEY specified for table '%s' (exactly one required)

What it means

The PRIMARY KEY was specified more than once for the same CREATE TABLE statement. The raw builder's setPartitionKeyColumns throws if partitionKeyColumns is already non-null, because exactly one PRIMARY KEY definition is allowed.

Solutions

  1. Specify the PRIMARY KEY exactly once — either inline on one column or as a trailing PRIMARY KEY (...) clause, not both
  2. In builder code, ensure only one code path calls setPartitionKeyColumns

Example fix

// before
CREATE TABLE t (a int PRIMARY KEY, b text, PRIMARY KEY (a));
// after
CREATE TABLE t (a int PRIMARY KEY, b text);
Defensive patterns

Strategy: validation

Validate before calling

const pkCount = (ddl.match(/PRIMARY\s+KEY/gi) || []).length + (ddl.match(/\b\w+\s+\w+\s+PRIMARY\s+KEY\b/gi) || []).length;
if (pkCount > 1) throw new Error('At most one PRIMARY KEY clause allowed');

Try / catch

try { session.execute(ddl); } catch (e) { if (/Multiple PRIMARY KEY/.test(e.message)) { /* remove the redundant PRIMARY KEY clause and retry */ } else throw e; }

Prevention

When it happens

Trigger: Calling PRIMARY KEY (a) inline on a column and also adding a trailing PRIMARY KEY (a) clause; calling setPartitionKeyColumns twice on the Raw builder; calling setPartitionKeyColumn (singular helper) after an explicit PRIMARY KEY clause.

Common situations: Mixing inline key syntax (a int PRIMARY KEY) with a separate PRIMARY KEY clause in generated DDL; programmatic schema assembly combining fragments that each set the partition key.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java:665

        public void addColumn(ColumnIdentifier column, CQL3Type.Raw type, boolean isStatic, ColumnMask.Raw mask, ColumnConstraints.Raw constraints)
        {
            addColumn(column, type, isStatic, false, mask, constraints);
        }

        public void setCompactStorage()
        {
            useCompactStorage = true;
        }

        public void setPartitionKeyColumn(ColumnIdentifier column)
        {
            setPartitionKeyColumns(Collections.singletonList(column));
        }

        public void setPartitionKeyColumns(List<ColumnIdentifier> columns)
        {
            if (null != partitionKeyColumns)
                throw ire("Multiple PRIMARY KEY specified for table '%s' (exactly one required)", name);

            partitionKeyColumns = columns;
        }

        public void markClusteringColumn(ColumnIdentifier column)
        {
            clusteringColumns.add(column);
        }

        public void extendClusteringOrder(ColumnIdentifier column, boolean ascending)
        {
            if (null != clusteringOrder.put(column, ascending))
                throw ire("Duplicate column '%s' in CLUSTERING ORDER BY clause for table '%s'", column, name);
        }
    }

    /**
     * Class encapsulating the properties of a column, which are its type and mask.

View on GitHub (pinned to 88fd0f6a0e)