apache/cassandra · error · MarshalException

Invalid unset value for field

Error message

Invalid unset value for field '%s' of user defined type %s

What it means

Unset sentinel values are only legal for multi-cell (non-frozen) UDTs. While validating elements, if the type is frozen (not multiCell) and a field's buffer equals the unset sentinel, this MarshalException names the field and type, because frozen values must be written in full.

Solutions

  1. Provide an explicit value for every field of the frozen UDT (use null to overwrite with an empty field if desired)
  2. Unfreeze the UDT (recreate as multi-cell) if partial updates with unset are required
  3. Check each buffer for the unset sentinel before constructing the value

Example fix

// before
buffers.set(1, Unset); // frozen UDT -> MarshalException
// after
if (!udt.isMultiCell() && buffer == unsetValue)
    buffer = fieldDefault; // explicit value instead of unset
buffers.set(1, buffer);
Defensive patterns

Strategy: validation

Validate before calling

if (!udt.isMultiCell()) for (int i=0;i<buffers.size();i++) if (buffers.get(i) == unsetValue) throw new IllegalArgumentException("unset not allowed for frozen field " + udt.fieldNameAsString(i));

Type guard

boolean unsetAllowed(UserType udt, Object buffer) { return udt.isMultiCell() || buffer != unsetValue; }

Try / catch

try { v = new UserType.Value(udt, buffers); } catch (MarshalException e) { throw new BindingException("frozen UDT cannot contain unset fields"); }

Prevention

When it happens

Trigger: Binding UNSET_BYTE_ARRAY / unset for a field of a frozen UDT in a constructor path; a prepared-statement bind variable left 'unset' for a frozen UDT field.

Common situations: Client using unset() on frozen UDT fields hoping to preserve existing values (explicitly unsupported); ORM-generated binds defaulting to unset; migration of code that worked when the UDT was later changed to frozen.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/db/marshal/UserType.java:697

    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("UDT value contained too many fields (expected %s, got %s)", size(), buffers.size()));

        for (int i = 0; i < buffers.size(); i++)
        {
            // Since a frozen UDT 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 (!isMultiCell() && buffer == unsetValue)
                throw new MarshalException(String.format("Invalid unset value for field '%s' of user defined type %s", fieldNameAsString(i), getNameAsString()));
            type(i).validate(buffer, valueAccessor);
        }

        return buffers;
    }

    @Override
    public SchemaElementType elementType()
    {
        return SchemaElementType.TYPE;
    }

    @Override
    public String elementKeyspace()
    {
        return keyspace;
    }

View on GitHub (pinned to 88fd0f6a0e)