apache/cassandra · error · MarshalException

Expected at least 3 bytes for a duration (%d)

Error message

Expected at least 3 bytes for a duration (%d)

What it means

A duration is encoded as three vints (months, days, nanoseconds); even minimal encodings occupy at least 3 bytes. validate() rejects values smaller than 3 bytes before attempting to decode, reporting the actual size.

Source

Thrown at src/java/org/apache/cassandra/serializers/DurationSerializer.java:83

        try (DataInputBuffer in = new DataInputBuffer(accessor.toBuffer(value), true))  // TODO: make a value input buffer
        {
            int months = in.readVInt32();
            int days = in.readVInt32();
            long nanoseconds = in.readVInt();
            return Duration.newInstance(months, days, nanoseconds);
        }
        catch (IOException e)
        {
            // this should never happen with a DataInputBuffer
            throw new AssertionError("Unexpected error", e);
        }
    }

    public <V> void validate(V value, ValueAccessor<V> accessor) throws MarshalException
    {
        if (accessor.size(value) < 3)
            throw new MarshalException(String.format("Expected at least 3 bytes for a duration (%d)", accessor.size(value)));

        try (DataInputBuffer in = new DataInputBuffer(accessor.toBuffer(value), true))  // FIXME: value input buffer
        {
            long monthsAsLong = in.readVInt();
            long daysAsLong = in.readVInt();
            long nanoseconds = in.readVInt();

            if (!canBeCastToInt(monthsAsLong))
                throw new MarshalException(String.format("The duration months must be a 32 bits integer but was: %d",
                                                         monthsAsLong));
            if (!canBeCastToInt(daysAsLong))
                throw new MarshalException(String.format("The duration days must be a 32 bits integer but was: %d",
                                                         daysAsLong));
            int months = (int) monthsAsLong;
            int days = (int) daysAsLong;

            if (!((months >= 0 && days >= 0 && nanoseconds >= 0) || (months <= 0 && days <=0 && nanoseconds <=0)))
                throw new MarshalException(String.format("The duration months, days and nanoseconds must be all of the same sign (%d, %d, %d)",

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Use DurationSerializer.serialize(Duration) to build the value
  2. Check column type vs stored bytes for schema mismatch
  3. Restore/repair truncated data from disk
  4. Never write hand-packed buffers; always pass a Duration instance

Example fix

// before
ByteBuffer bad = ByteBufferUtil.bytes(new byte[]{1, 2}); // too short
// after
ByteBuffer ok = DurationSerializer.instance.serialize(Duration.newInstance(1, 2, 3));
Defensive patterns

Strategy: validation

Validate before calling

public static void checkDuration(ByteBuffer buf) {
    if (buf != null && buf.remaining() > 0 && buf.remaining() < 3)
        throw new MarshalException("duration too short: " + buf.remaining());
}

Type guard

public static boolean isPlausibleDurationBytes(ByteBuffer buf) {
    return buf == null || !buf.hasRemaining() || buf.remaining() >= 3;
}

Try / catch

try {
    Duration d = DurationSerializer.instance.deserialize(buffer);
} catch (MarshalException e) {
    logger.warn("Invalid duration bytes: {}", e.getMessage());
}

Prevention

When it happens

Trigger: validate/deserialize on a buffer of 0-2 bytes for a duration column — truncated cell, empty-but-non-null value, or wrong-typed bytes stored in a duration column.

Common situations: Application writing an int/short into a duration column; partially written data; schema drift where the column previously held another type.

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


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