apache/cassandra · error · InvalidRequestException
is not a valid field identifier of type
Error message
%s is not a valid field identifier of type %s
What it means
When building a UDT selector from a UDT literal in the selection clause, the left side of a `{field: value}` pair is not a plain identifier, so it cannot be resolved to a field of the user type. Only RawIdentifier keys are valid field names. The request is rejected at prepare time.
Solutions
- Use a plain (possibly quoted) field name as the key: {street:'x'} instead of an expression key.
- Check that the literal is a UDT literal and not intended as a tuple literal (tuples use (v1, v2) syntax).
- Validate programmatically generated UDT literal keys are FieldIdentifier-compatible names.
Example fix
// before
SELECT (address) {street(x):'Main'} FROM t;
// after
SELECT (address) {street:'Main'} FROM t; Defensive patterns
Strategy: validation
Validate before calling
for (String key : literalKeys) if (!key.matches("[a-zA-Z_][a-zA-Z0-9_]*") && !key.startsWith("\"")) throw new IllegalArgumentException("UDT literal key must be a plain identifier: " + key); Try / catch
try { session.execute(stmt); } catch (InvalidRequestException e) { if (e.getMessage().contains("not a valid field identifier")) { /* fix the UDT literal key to a plain identifier */ } else throw e; } Prevention
- Generate UDT literal keys from schema field names only.
- Never interpolate expressions into the key position of UDT literals.
- Distinguish tuple literal syntax from UDT literal syntax in query builders.
When it happens
Trigger: `SELECT (udt_type) {f(x):1} FROM t` or a computed/function-call expression used as the field key of a UDT literal; a quoted or nested expression where a simple field identifier is expected.
Common situations: Copy-paste typos in UDT literals; programmatically generated literals where keys are expressions rather than names; confused tuple syntax `{1,2}` vs UDT syntax `{field:val}`.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- A user type cannot contain counters
- A user type cannot contain non-frozen UDTs
- Altering field types is no longer supported
- Argument ' ' cannot be frozen; remove frozen<> modifier from
- Cannot add field to type : a field with name already exists
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/55dd64012a558ff5.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/selection/Selectable.java:1162
return MapSelector.newFactory(type, getMapEntries(cfm).stream()
.map(p -> Pair.create(p.left.newSelectorFactory(cfm, mapType.getKeysType(), defs, boundNames),
p.right.newSelectorFactory(cfm, mapType.getValuesType(), defs, boundNames)))
.collect(Collectors.toList()));
}
private Factory newUdtSelectorFactory(TableMetadata cfm,
AbstractType<?> expectedType,
List<ColumnMetadata> defs,
VariableSpecifications boundNames)
{
UserType ut = (UserType) expectedType;
Map<FieldIdentifier, Factory> factories = new LinkedHashMap<>(ut.size());
for (Pair<Selectable.Raw, Selectable.Raw> raw : raws)
{
if (!(raw.left instanceof RawIdentifier))
throw invalidRequest("%s is not a valid field identifier of type %s ",
raw.left,
ut.getNameAsString());
FieldIdentifier fieldName = ((RawIdentifier) raw.left).toFieldIdentifier();
int fieldPosition = ut.fieldPosition(fieldName);
if (fieldPosition == -1)
throw invalidRequest("Unknown field '%s' in value of user defined type %s",
fieldName,
ut.getNameAsString());
AbstractType<?> fieldType = ut.fieldType(fieldPosition);
factories.put(fieldName,
raw.right.prepare(cfm).newSelectorFactory(cfm, fieldType, defs, boundNames));
}
return UserTypeSelector.newFactory(expectedType, factories);
}View on GitHub (pinned to 88fd0f6a0e)