apache/cassandra · error · MarshalException
The duration months must be a 32 bits integer but was: %d
Error message
The duration months must be a 32 bits integer but was: %d
What it means
After decoding the vints, validate() checks the months field fits in a signed 32-bit int. Vints can carry larger values, so an out-of-int-range months component cannot be represented as Duration's int fields and is rejected with this MarshalException.
Source
Thrown at src/java/org/apache/cassandra/serializers/DurationSerializer.java:92
{
// 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)",
months, days, nanoseconds));
}
catch (IOException e)
{
// this should never happen with a DataInputBuffer
throw new AssertionError("Unexpected error", e);
}
}
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Ensure durations are constructed via Duration.newInstance(int months, int days, long nanos) which enforces int months
- Re-serialize with the official serializer instead of hand-packed vints
- Check data integrity if value came from storage
- If input comes from user strings, validate ranges before conversion
Example fix
// before byte[] packed = packVInt(Long.valueOf(Integer.MAX_VALUE) + 1); // months out of int range // after Duration d = Duration.newInstance(12, 0, 0); // months fits int ByteBuffer ok = DurationSerializer.instance.serialize(d);
Defensive patterns
Strategy: validation
Validate before calling
public static boolean monthsFitsInt(long months) {
return months >= Integer.MIN_VALUE && months <= Integer.MAX_VALUE;
} Type guard
public static boolean isEncodableDuration(long months, long days, long nanos) {
return monthsFitsInt(months) && days >= Integer.MIN_VALUE && days <= Integer.MAX_VALUE;
} Try / catch
try {
serializer.validate(buffer, accessor);
} catch (MarshalException e) {
if (e.getMessage().contains("months must be a 32 bits")) logger.error("months overflow");
} Prevention
- Keep month components small (Cassandra limits to signed int anyway)
- Parse duration strings via Duration.from which enforces bounds
- Fuzz-test any custom duration parsing
When it happens
Trigger: validate/deserialize of a duration whose encoded months vint exceeds Integer.MAX_VALUE or is below Integer.MIN_VALUE — typically hand-crafted or corrupted bytes, since normal Duration construction uses ints.
Common situations: Corrupted SSTable bytes decoded as huge vints; manually packing vints with values beyond int range; fuzz/malformed input on user-supplied duration strings via native protocol.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- The duration days must be a 32 bits integer but was: %d
- Expected at least 3 bytes for a duration (%d)
- The duration months, days and nanoseconds must be all of the
- Input date %s is greater than max supported date %s
- Unable to make long (for time) from: '%s'
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/0093566c58fda1a0.
Report an issue: GitHub.