apache/cassandra · error · InvalidRequestException
Invalid unset value for tuple field number
Error message
Invalid unset value for tuple field number %d
What it means
During filterSortAndValidateElements, a field buffer equal to the sentinel unset marker (UNSET_BYTE_ARRAY) is rejected with InvalidRequestException. Cassandra writes tuples in their entirety, so an 'unset' individual field cannot preserve a previous value; the driver must instead omit or fully supply the tuple.
Solutions
- Supply a complete tuple value (all fields set, or the whole tuple null) instead of per-field unset markers
- Rewrite the update to replace the whole tuple in one statement
- If a partial update is needed, read-modify-write: SELECT the tuple, merge in the app, UPDATE the full value
- Check driver documentation for how it encodes unset values and avoid it for tuple fields
Example fix
// before: binding with unset field stmt.bind(id, UNSET, value); // after: bind the whole tuple or null TupleValue full = elementType.newValue(null, value); // explicit full tuple stmt.bind(id, full);
Defensive patterns
Strategy: validation
Validate before calling
for (Object f : fields)
if (f == null || isUnsetMarker(f))
throw new IllegalArgumentException("tuples cannot contain unset fields; supply the full value"); Try / catch
try {
tupleType.bind(fields);
} catch (InvalidRequestException e) {
// unset field inside tuple: rewrite as full tuple or whole-column update
} Prevention
- Always write tuples atomically as complete values
- Avoid mapping per-field bind markers onto tuple columns
- Implement partial updates as read-modify-write of the whole tuple
When it happens
Trigger: Binding a query where a driver sends an unset marker for one tuple element (common when using bind markers with partial assignment); calling filterSortAndValidateElements with the unset sentinel present in the buffers list.
Common situations: Using prepared statements where some bound variables are left unset inside a tuple value; ORMs or client libraries that map nulls to unset markers; partial-update logic applied to a tuple column.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Counters are not allowed inside tuples
- Expected elements in value for tuple , but got
- Invalid operation ( ) for tuple column
- Invalid tuple literal for
- Invalid tuple literal for
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/61a0f0b07b9e1cfe.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/db/marshal/TupleType.java:417
@Override
public List<byte[]> filterSortAndValidateElementsFromArrays(List<byte[]> buffers)
{
return filterSortAndValidateElements(buffers, ByteArrayUtil.UNSET_BYTE_ARRAY, ByteArrayAccessor.instance);
}
private <T> List<T> filterSortAndValidateElements(List<T> buffers, T unsetValue, ValueAccessor<T> valueAccessor)
{
if (buffers.size() > size())
throw new MarshalException(String.format("Tuple value contains too many fields (expected %s, got %s)", size(), buffers.size()));
for (int i = 0; i < buffers.size(); i++)
{
// Since A tuple value is always written in its entirety Cassandra can't preserve a pre-existing value by 'not setting' the new value. Reject the query.
T buffer = buffers.get(i);
if (buffer == null)
continue;
if (buffer == unsetValue)
throw new InvalidRequestException(String.format("Invalid unset value for tuple field number %d", i));
type(i).validate(buffer, valueAccessor);
}
return buffers;
}
@Override
public <V> String getString(V input, ValueAccessor<V> accessor)
{
if (input == null)
return "null";
StringBuilder sb = new StringBuilder();
int offset = 0;
for (int i = 0; i < size(); i++)
{
if (accessor.isEmptyFromOffset(input, offset))
return sb.toString();View on GitHub (pinned to 88fd0f6a0e)