apache/cassandra · error · InvalidRequestException

Invalid operation (%s) for frozen UDT column %s

Error message

Invalid operation (%s) for frozen UDT column %s

What it means

Cassandra throws this during preparation when a UDT field update is applied to a frozen UDT column. Frozen UDTs are stored as one immutable blob, so individual fields cannot be updated in place; the entire UDT value must be replaced.

Source

Thrown at src/java/org/apache/cassandra/cql3/Operation.java:299

    }

    public static class SetField implements RawUpdate
    {
        private final FieldIdentifier field;
        private final Term.Raw value;

        public SetField(FieldIdentifier field, Term.Raw value)
        {
            this.field = field;
            this.value = value;
        }

        public Operation prepare(TableMetadata metadata, ColumnMetadata receiver, boolean canReadExistingState) throws InvalidRequestException
        {
            if (!receiver.type.isUDT())
                throw new InvalidRequestException(String.format("Invalid operation (%s) for non-UDT column %s", toString(receiver), receiver.name));
            else if (!receiver.type.isMultiCell())
                throw new InvalidRequestException(String.format("Invalid operation (%s) for frozen UDT column %s", toString(receiver), receiver.name));

            int fieldPosition = ((UserType) receiver.type).fieldPosition(field);
            if (fieldPosition == -1)
                throw new InvalidRequestException(String.format("UDT column %s does not have a field named %s", receiver.name, field));

            Term val = value.prepare(metadata.keyspace, UserTypes.fieldSpecOf(receiver, fieldPosition));
            return new UserTypes.SetterByField(receiver, field, val);
        }

        protected String toString(ColumnSpecification column)
        {
            return String.format("%s.%s = %s", column.name, field, value);
        }

        public boolean isCompatibleWith(RawUpdate other)
        {
            if (other instanceof SetField)
                return !((SetField) other).field.equals(field);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Replace the whole frozen UDT value: SET myudt = {field1: v1, field2: v2, ...}
  2. If per-field updates are required, migrate to a non-frozen UDT column (add new column, copy data, drop old)
  3. Update application/ORM code to always send complete frozen UDT values

Example fix

// before (address frozen<address_udt>)
UPDATE users SET address.city = 'NYC' WHERE id = 1;
// after
UPDATE users SET address = {street:'5th Ave', city:'NYC', zip:'10001'} WHERE id = 1;
Defensive patterns

Strategy: validation

Validate before calling

AbstractType<?> t = tm.getColumn(col).getType();
if (t.isUDT() && !t.isMultiCell())
    throw new IllegalArgumentException(col + " is a frozen UDT; assign the complete value");

Type guard

boolean isFrozenUdt(AbstractType<?> t) { return t.isUDT() && !t.isMultiCell(); }

Try / catch

try { session.execute(update); } catch (InvalidRequestException e) { if (e.getMessage().contains("frozen UDT")) writeFullUdt(); else throw e; }

Prevention

When it happens

Trigger: Executing 'UPDATE t SET myudt.field = v WHERE ...' where myudt is declared frozen<some_udt>; isMultiCell() returns false and prepare() rejects the field-level setter.

Common situations: Tables modelled before Cassandra 3.x / UDT unfreezing support; developer unaware the UDT was created with FROZEN; migration scripts that froze UDTs for compatibility.

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/b94673599e045fac. Report an issue: GitHub.