apache/cassandra · error · InvalidRequestException

Invalid field deletion operation for non-UDT column %s

Error message

Invalid field deletion operation for non-UDT column %s

What it means

A UDT field deletion (`DELETE col.field FROM t`) was issued against a column that is not a user-defined type. Field-level deletes only apply to non-frozen UDT columns, so prepare rejects non-UDT receivers.

Source

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

    {
        private final ColumnIdentifier id;
        private final FieldIdentifier field;

        public FieldDeletion(ColumnIdentifier id, FieldIdentifier field)
        {
            this.id = id;
            this.field = field;
        }

        public ColumnIdentifier affectedColumn()
        {
            return id;
        }

        public Operation prepare(String keyspace, ColumnMetadata receiver, TableMetadata metadata) throws InvalidRequestException
        {
            if (!receiver.type.isUDT())
                throw new InvalidRequestException(String.format("Invalid field deletion operation for non-UDT column %s", receiver.name));
            else if (!receiver.type.isMultiCell())
                throw new InvalidRequestException(String.format("Frozen UDT column %s does not support field deletions", receiver.name));

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

            return new UserTypes.DeleterByField(receiver, field);
        }
    }
}

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Confirm the target column is a non-frozen UDT with DESCRIBE TYPE / DESCRIBE TABLE
  2. Delete the whole column (DELETE col FROM t) and rewrite it without the field if it is not a UDT
  3. Fix the column name if a typo was made
  4. Note frozen UDTs do not support field deletions either — use full-value replacement there

Example fix

// before (address is frozen UDT / text)
DELETE address.city FROM t WHERE id=1;
// after (non-frozen UDT)
DELETE address.city FROM t WHERE id=1;
// or full replacement for frozen:
UPDATE t SET address = {city:'X', zip:'Y'} WHERE id=1;
Defensive patterns

Strategy: validation

Validate before calling

String type = session.execute("SELECT type FROM system_schema.columns WHERE keyspace_name=? AND table_name=? AND column_name=?", ks, table, col).one().getString("type");
if (type.contains("<") && !type.startsWith("frozen<")) { /* UDT check */ }
// confirm a UDT of this name exists:
session.execute("SELECT field_names FROM system_schema.types WHERE keyspace_name=? AND type_name=?", ks, udtName);

Try / catch

try { session.execute("DELETE col.field FROM t WHERE id=?", id); } catch (InvalidQueryException e) { if (e.getMessage().contains("non-UDT column")) { /* fix column or delete whole column */ } else throw e; }

Prevention

When it happens

Trigger: `DELETE address.city FROM t` where address is not a UDT (scalar or collection); typo in the column name.

Common situations: Confusing nested syntax across column kinds; schema drift where the UDT was replaced by a simpler type; copy-pasted statements between tables.

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