apache/cassandra · error · MarshalException
Expected 8 or 0 byte long for date (%d)
Error message
Expected 8 or 0 byte long for date (%d)
What it means
TimestampSerializer.validate accepts values that are exactly 8 bytes (a long of epoch millis) or empty (0 bytes, historically allowed for timestamps). Any other length fails this check, meaning the binary payload is not a valid timestamp encoding.
Source
Thrown at src/java/org/apache/cassandra/serializers/TimestampSerializer.java:188
return ZonedDateTime.parse(source, fmt).toInstant().toEpochMilli();
}
catch (DateTimeParseException e)
{
continue;
}
}
throw new MarshalException(String.format("Unable to parse a date/time from '%s'", source));
}
public static Format getJsonDateFormatter()
{
return FORMATTER_TO_JSON.get();
}
public <V> void validate(V value, ValueAccessor<V> accessor) throws MarshalException
{
if (accessor.size(value) != 8 && !accessor.isEmpty(value))
throw new MarshalException(String.format("Expected 8 or 0 byte long for date (%d)", accessor.size(value)));
}
public String toString(Date value)
{
return toStringUTC(value);
}
public String toStringUTC(Date value)
{
return value == null ? "" : FORMATTER_UTC.get().format(value.toInstant());
}
public Class<Date> getType()
{
return Date.class;
}
@OverrideView on GitHub (pinned to 88fd0f6a0e)
Solutions
- Ensure exactly 8 bytes: ByteBuffer.allocate(8).putLong(epochMillis)
- Use the driver's timestamp codec with java.util.Date/Instant instead of raw buffers
- Verify the column type via driver metadata before binding
- If empty values are intentional, keep them truly 0-length, not partial writes
Example fix
// before ByteBuffer v = ByteBuffer.allocate(4).putInt(42); // after ByteBuffer v = ByteBuffer.allocate(8).putLong(Instant.now().toEpochMilli());
Defensive patterns
Strategy: type-guard
Validate before calling
if (buf != null && buf.remaining() != 8 && buf.remaining() != 0) throw new IllegalArgumentException("timestamp must be 8 bytes or empty, got " + buf.remaining()); Type guard
boolean isWellFormedTimestampBytes(ByteBuffer v) { return v == null || v.remaining() == 0 || v.remaining() == 8; } Try / catch
try {
serializer.validate(value, byteBufferAccessor);
} catch (MarshalException e) {
throw new DataCorruptionException("unexpected byte width for timestamp column", e);
} Prevention
- Always allocate exactly 8 bytes for timestamps
- Bind Instant/Date via driver codecs instead of raw buffers
- Compare column type metadata before cross-type reads
- Audit ETL code that slices or resizes buffers
When it happens
Trigger: Binding a 4-byte int, a 16-byte value, or truncated bytes as a timestamp; deserializing a column whose bytes came from a different CQL type; hand-built payloads in custom serialization code.
Common situations: Schema mismatch after ALTER TYPE (e.g. int/date columns read as timestamp); drivers using wrong codecs; corrupted data from broken ETL that sliced buffers incorrectly.
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
- Expected 4 byte long for date (%d)
- Expected 8 byte long for time (%d)
- Unable to make long (for date) from: '%s'
- Unable to parse a date/time from '%s'
- Not enough bytes to read size of %dth field %s
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/ef8660c352320b6d.
Report an issue: GitHub.