apache/cassandra · error · MarshalException
The duration days must be a 32 bits integer but was: %d
Error message
The duration days must be a 32 bits integer but was: %d
What it means
MarshalException raised by DurationSerializer.validate after decoding the three VInt components of a duration: the days component exceeds the 32-bit int range that the duration type guarantees (enforced by canBeCastToInt). The value being read was not written by a valid duration encoder or is corrupt.
Source
Thrown at src/java/org/apache/cassandra/serializers/DurationSerializer.java:95
}
}
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);
}
}
/**
* Checks that the specified {@code long} can be cast to an {@code int} without information lost.
*View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Construct durations with Duration.newInstance ensuring days fits an int
- Re-serialize via DurationSerializer rather than manual vint packing
- Verify integrity of stored bytes if corruption is suspected
- Validate user-provided durations before serializing
Example fix
// before long days = 1L << 40; byte[] packed = packVInt(days); // out of int range // after Duration d = Duration.newInstance(0, (int) 30, 0); ByteBuffer ok = DurationSerializer.instance.serialize(d);
Defensive patterns
Strategy: validation
Validate before calling
public static boolean daysFitsInt(long days) {
return days >= Integer.MIN_VALUE && days <= Integer.MAX_VALUE;
} Type guard
public static boolean isSafeDayCount(long days) {
return daysFitsInt(days);
} Try / catch
try {
serializer.validate(buffer, accessor);
} catch (MarshalException e) {
if (e.getMessage().contains("days must be a 32 bits")) logger.error("days overflow");
} Prevention
- Compute day offsets with int-safe arithmetic before newInstance
- Validate user input day counts
- Avoid hand-encoded vints
When it happens
Trigger: validate/deserialize of a duration whose days vint decodes to a value outside int range — corrupted bytes or hand-encoded vints with oversized day counts.
Common situations: Storage corruption; custom serialization writing days as a long vint beyond int bounds; malformed user input converted without range checks.
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 months 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/44ed9ca9fa9a7572.
Report an issue: GitHub.