apache/cassandra · error · IllegalStateException
Function argument is not a tuple type but a
Error message
Function argument is not a tuple type but a ${dataType.getName()} What it means
IllegalStateException guard in UDFContextImpl: a UDF argument declared as a tuple/UDT value is actually of a different CQL type kind, so the requested value object cannot be created. Note the message is a template bug — it prints the literal '${dataType.getName()}' instead of interpolating — and the shown guard actually lives in newUDTValue checking for UserType; treat it as a generic type-kind mismatch sentinel.
Solutions
- Use newTupleValue/newArgTupleValue only for arguments declared as tuple<...> in CREATE FUNCTION
- For UDT arguments use newUDTValue/newArgUDTValue instead
- Double-check the argument index or name against the function's declared argument list
Example fix
// before
TupleValue tv = context.newArgTupleValue("udt_arg");
// after
UDTValue uv = context.newArgUDTValue("udt_arg"); Defensive patterns
Strategy: type-guard
Validate before calling
// Only request tuple values for tuple-typed arguments:
if (!(argType instanceof TupleType)) throw new IllegalArgumentException("arg is not a tuple: " + argType); Type guard
boolean isTuple(DataType t) { return t instanceof TupleType; } Try / catch
try { TupleValue tv = ctx.newArgTupleValue(i); }
catch (IllegalStateException e) {
if (e.getMessage().contains("not a tuple")) { /* use UDT/collection accessor as appropriate */ }
else throw e;
} Prevention
- Distinguish tuple<...> from UDTs in the function signature before choosing an accessor
- Validate argument names/indices against the declared CREATE FUNCTION list
When it happens
Trigger: Calling udfContext.newTupleValue() or newArgTupleValue(index/name) where the argument's type is not a CQL tuple — e.g. a UDT, collection, or scalar.
Common situations: UDF code written for tuple arguments being reused on UDT arguments (both are composite, easy to confuse); argument index off-by-one after editing the function signature.
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
- Function argument is not a UDT but a
- Cannot replace function
- Function does not declare an argument with index
- Invalid tuple literal for
- Invalid tuple type literal for
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/f5f5c224bcc5854b.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/functions/UDFContextImpl.java:128
public TupleValue newTupleValue(String cqlDefinition)
{
AbstractType<?> abstractType = CQLTypeParser.parse(keyspace, cqlDefinition, metadata.get().types);
DataType dataType = JavaDriverUtils.driverType(abstractType);
return newTupleValue(dataType);
}
private static UDTValue newUDTValue(DataType dataType)
{
if (!(dataType instanceof UserType))
throw new IllegalStateException("Function argument is not a UDT but a " + dataType.getName());
UserType userType = (UserType) dataType;
return userType.newValue();
}
private static TupleValue newTupleValue(DataType dataType)
{
if (!(dataType instanceof TupleType))
throw new IllegalStateException("Function argument is not a tuple type but a " + dataType.getName());
TupleType tupleType = (TupleType) dataType;
return tupleType.newValue();
}
private UDFDataType getArgumentTypeByIndex(int index)
{
if (index < 0 || index >= argTypes.size())
throw new IllegalArgumentException("Function does not declare an argument with index " + index);
return argTypes.get(index);
}
private UDFDataType getArgumentTypeByName(String argName)
{
UDFDataType arg = byName.get(argName);
if (arg == null)
throw new IllegalArgumentException("Function does not declare an argument named '" + argName + '\'');
return arg;
}View on GitHub (pinned to 88fd0f6a0e)