apache/cassandra · error · MarshalException
Expected 4 byte long for date (%d)
Error message
Expected 4 byte long for date (%d)
What it means
SimpleDateSerializer.validate checks that the binary value of a 'date' column is exactly 4 bytes, matching the unsigned-int day encoding. This error is thrown when deserializing/validating a value whose byte length differs, meaning the stored or transmitted bytes are not a valid date encoding.
Source
Thrown at src/java/org/apache/cassandra/serializers/SimpleDateSerializer.java:121
{
throw new MarshalException(String.format("Unable to make unsigned int (for date) from: '%s'", source), e);
}
}
public static int timeInMillisToDay(long millis)
{
return (int) (Duration.ofMillis(millis).toDays() - Integer.MIN_VALUE);
}
public static long dayToTimeInMillis(int days)
{
return Duration.ofDays(days + Integer.MIN_VALUE).toMillis();
}
public <V> void validate(V value, ValueAccessor<V> accessor) throws MarshalException
{
if (accessor.size(value) != 4)
throw new MarshalException(String.format("Expected 4 byte long for date (%d)", accessor.size(value)));
}
public String toString(Integer value)
{
if (value == null)
return "";
return Instant.ofEpochMilli(dayToTimeInMillis(value)).atZone(UTC).format(formatter);
}
public Class<Integer> getType()
{
return Integer.class;
}
@Override
public boolean shouldQuoteCQLLiterals()
{View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Ensure exactly 4 bytes are supplied: encode via SimpleDateSerializer (timeInMillisToDay result as unsigned int)
- Do not pass a java.util.Date/long (8 bytes) where a date is expected; convert days encoding instead
- Check the column's actual type with the driver's table metadata before binding
- If legacy 0/empty values exist, handle empties before calling validate/deserialize
Example fix
// before
ByteBuffer v = ByteBuffer.allocate(8).putLong(System.currentTimeMillis());
// after
int days = SimpleDateSerializer.timeInMillisToDay(System.currentTimeMillis());
ByteBuffer v = TypeCodec.bigint().serialize(...); // or dateCodec.serialize("2011-02-03") Defensive patterns
Strategy: type-guard
Validate before calling
if (buf == null || buf.remaining() != 4) throw new IllegalArgumentException("date value must be exactly 4 bytes, got " + (buf == null ? 0 : buf.remaining())); Type guard
boolean isWellFormedDateBytes(ByteBuffer v) { return v != null && v.remaining() == 4; } Try / catch
try {
serializer.validate(value, byteBufferAccessor);
} catch (MarshalException e) {
throw new DataCorruptionException("non-4-byte value in date column", e);
} Prevention
- Always produce date bytes through SimpleDateSerializer, never by hand
- Check table metadata column types before binding raw buffers
- Guard against schema drift between environments
- Validate external binary data at ingestion
When it happens
Trigger: Binding a 0-byte, 8-byte (long/timestamp bytes), or truncated buffer as a date value; reading a date column from a table written by a different type; passing a Java Date's 8-byte time encoding where 4-byte date encoding is required.
Common situations: Schema drift after ALTER TYPE or migration from timestamp to date; driver/client sending full timestamps into date columns; corrupted sstable data or hand-crafted byte payloads in custom code.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Input date %s is less than min supported date %s
- Input date %s is greater than max supported date %s
- Unable to coerce '%s' to a formatted date (long)
- Unable to make unsigned int (for date) from: '%s'
- Expected 8 byte long for time (%d)
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/396df36071c85b7f.
Report an issue: GitHub.