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
- Replace the whole frozen UDT value: SET myudt = {field1: v1, field2: v2, ...}
- If per-field updates are required, migrate to a non-frozen UDT column (add new column, copy data, drop old)
- 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
- Record FROZEN modifiers in your schema model and generate full-value writes for them
- Prefer non-frozen UDTs when per-field updates are needed
- Test update paths against the production schema shape
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
- Invalidate CIDR permissions cache operation not supported by
- Not enough bytes to read size of %dth field %s
- Not enough bytes to read %dth field %s
- frozen<> is only allowed on collections, tuples, and user-de
- Non-frozen UDTs are not allowed inside collections:
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/b94673599e045fac.
Report an issue: GitHub.