apache/cassandra · error · InvalidRequestException

Invalid field selection

Error message

Invalid field selection: %s of type %s is not a user type

What it means

Field selection (col.field for user-defined types) requires the selected expression to have a UDT type. If the underlying selector's return type, unwrapped, is not a UserType, the field access is meaningless and the query is rejected.

Solutions

  1. Verify the column type in DESCRIBE TABLE is a user-defined type
  2. Apply field selection directly to the UDT column, not to a function result that returns a non-UDT
  3. Use dot notation only for UDTs; index collections with [] instead

Example fix

// before
SELECT address.city FROM t WHERE address IS text;
// after
ALTER TABLE t ALTER ... / use a UDT: SELECT addr.city FROM t; // addr is an address UDT
Defensive patterns

Strategy: type-guard

Validate before calling

AbstractType<?> t = col.getType().unwrap();
if (!(t instanceof UserType)) throw new IllegalArgumentException(col + " is not a UDT");

Type guard

boolean isUdt(ColumnMetadata c) { return c.getType().unwrap() instanceof UserType; }

Prevention

When it happens

Trigger: SELECT c.field FROM t where c is a plain column (e.g. text/int/collection) rather than a UDT, or where a wrapping function changed the return type away from the UDT.

Common situations: Copy-pasting field-selection syntax onto non-UDT columns, or forgetting that an intermediate function/cast changed the type so .field no longer applies.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/selection/Selectable.java:567

            return String.format("%s.%s", selected, field);
        }

        public Selector.Factory newSelectorFactory(TableMetadata table, AbstractType<?> expectedType, List<ColumnMetadata> defs, VariableSpecifications boundNames)
        {
            AbstractType<?> expectedUdtType = null;

            // If the UDT is between parentheses, we know that it is not a tuple with a single element.
            if (selected instanceof BetweenParenthesesOrWithTuple)
            {
                BetweenParenthesesOrWithTuple betweenParentheses = (BetweenParenthesesOrWithTuple) selected;
                expectedUdtType = betweenParentheses.selectables.get(0).getExactTypeIfKnown(table.keyspace);
            }

            Selector.Factory factory = selected.newSelectorFactory(table, expectedUdtType, defs, boundNames);
            AbstractType<?> type = factory.getReturnType().unwrap();
            if (!type.isUDT())
            {
                throw new InvalidRequestException(
                        String.format("Invalid field selection: %s of type %s is not a user type",
                                selected,
                                type.asCQL3Type()));
            }

            UserType ut = (UserType) type;
            int fieldIndex = ut.fieldPosition(field);
            if (fieldIndex == -1)
            {
                throw new InvalidRequestException(String.format("%s of type %s has no field %s",
                        selected, type.asCQL3Type(), field));
            }

            return FieldSelector.newFactory(ut, fieldIndex, factory);
        }

        public AbstractType<?> getExactTypeIfKnown(String keyspace)
        {

View on GitHub (pinned to 88fd0f6a0e)