apache/cassandra · error · InvalidRequestException

Cannot add new field %s of type %s to user type %s as the ty

Error message

Cannot add new field %s of type %s to user type %s as the type is being used in partition key by the following tables: %s

What it means

Cassandra refuses to add a field to a UDT that is used (unfrozen) in any table's partition key, because changing the type would change partition key serialization and make existing rows unreachable. AddField.apply enumerates tables and views whose partition key columns reference the UDT and rejects the ALTER with the list of offending tables.

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/AlterTypeStatement.java:162

            if (type.isUDT() && !type.isFrozen())
                throw ire("A user type cannot contain non-frozen UDTs");

            if (userType.fieldPosition(fieldName) >= 0)
            {
                if (!ifFieldNotExists)
                    throw ire("Cannot add field %s to type %s: a field with name %s already exists", fieldName, userType.getCqlTypeName(), fieldName);
                return userType;
            }

            AbstractType<?> fieldType = type.prepare(keyspaceName, keyspace.types).getType();
            if (fieldType.referencesUserType(userType.name))
                throw ire("Cannot add new field %s of type %s to user type %s as it would create a circular reference", fieldName, type, userType.getCqlTypeName());

            Collection<TableMetadata> tablesWithTypeInPartitionKey = findTablesReferencingTypeInPartitionKey(keyspace, userType);
            if (!tablesWithTypeInPartitionKey.isEmpty())
            {
                throw ire("Cannot add new field %s of type %s to user type %s as the type is being used in partition key by the following tables: %s",
                          fieldName, type, userType.getCqlTypeName(),
                          String.join(", ", transform(tablesWithTypeInPartitionKey, TableMetadata::toString)));
            }

            Guardrails.fieldsPerUDT.guard(userType.size() + 1, userType.getNameAsString(), false, state);
            type.validate(state, "Field " + fieldName);

            List<FieldIdentifier> fieldNames = new ArrayList<>(userType.fieldNames()); fieldNames.add(fieldName);
            List<AbstractType<?>> fieldTypes = new ArrayList<>(userType.fieldTypes()); fieldTypes.add(fieldType);

            return new UserType(keyspaceName, userType.name, fieldNames, fieldTypes, true);
        }

        private static Collection<TableMetadata> findTablesReferencingTypeInPartitionKey(KeyspaceMetadata keyspace, UserType userType)
        {
            Collection<TableMetadata> tables = new ArrayList<>();
            filter(keyspace.tablesAndViews(),
                   table -> any(table.partitionKeyColumns(), column -> column.type.referencesUserType(userType.name)))

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Drop and recreate dependent tables without the UDT in the partition key, add the field, then recreate/repopulate the data
  2. Create a new table with a different design (e.g. freeze the UDT or move it to a regular column), migrate data, drop the old table
  3. Use a new UDT version (e.g. addr_v2) for the new schema and migrate tables away from the old type

Example fix

// before
CREATE TABLE events (k frozen<addr>, ... PRIMARY KEY ((k), ts)); -- still blocks add
-- after: move UDT out of partition key
CREATE TABLE events (id uuid, k addr, ..., PRIMARY KEY (id, ts));
Defensive patterns

Strategy: validation

Validate before calling

// Before altering a UDT, check partition-key usage:
ResultSet rs = session.execute("SELECT table_name, column_name FROM system_schema.columns " +
    "WHERE keyspace_name='myks' AND kind='partition_key'");
// verify none of the partition key column types reference the UDT before ALTER TYPE ... ADD

Try / catch

try { session.execute(alterTypeCql); }
catch (InvalidQueryException e) {
    if (e.getMessage().contains("used in partition key")) { /* migrate tables listed in the message first */ }
    else throw e;
}

Prevention

When it happens

Trigger: `ALTER TYPE myks.addr ADD zip text` where some table was created with `PRIMARY KEY ((addr), ...)` containing the addr UDT unfrozen in the partition key.

Common situations: UDTs accidentally placed in partition keys early in design, then needing evolution later; multi-DC migrations where schema drift re-introduced the UDT into a partition key.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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