{"record":{"id":"ef8660c352320b6d","repo":"apache/cassandra","slug":"expected-8-or-0-byte-long-for-date-d","errorCode":null,"errorMessage":"Expected 8 or 0 byte long for date (%d)","messagePattern":"Expected 8 or 0 byte long for date \\((.+?)\\)","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/serializers/TimestampSerializer.java","lineNumber":188,"sourceCode":"                return ZonedDateTime.parse(source, fmt).toInstant().toEpochMilli();\n            }\n            catch (DateTimeParseException e)\n            {\n                continue;\n            }\n        }\n        throw new MarshalException(String.format(\"Unable to parse a date/time from '%s'\", source));\n    }\n\n    public static Format getJsonDateFormatter()\n    {\n    \treturn FORMATTER_TO_JSON.get();\n    }\n\n    public <V> void validate(V value, ValueAccessor<V> accessor) throws MarshalException\n    {\n        if (accessor.size(value) != 8 && !accessor.isEmpty(value))\n            throw new MarshalException(String.format(\"Expected 8 or 0 byte long for date (%d)\", accessor.size(value)));\n    }\n\n    public String toString(Date value)\n    {\n        return toStringUTC(value);\n    }\n\n    public String toStringUTC(Date value)\n    {\n        return value == null ? \"\" : FORMATTER_UTC.get().format(value.toInstant());\n    }\n\n    public Class<Date> getType()\n    {\n        return Date.class;\n    }\n\n    @Override","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/serializers/TimestampSerializer.java#L170-L206","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nByteBuffer v = ByteBuffer.allocate(4).putInt(42);\n// after\nByteBuffer v = ByteBuffer.allocate(8).putLong(Instant.now().toEpochMilli());","handlingStrategy":"type-guard","validationCode":"if (buf != null && buf.remaining() != 8 && buf.remaining() != 0) throw new IllegalArgumentException(\"timestamp must be 8 bytes or empty, got \" + buf.remaining());","typeGuard":"boolean isWellFormedTimestampBytes(ByteBuffer v) { return v == null || v.remaining() == 0 || v.remaining() == 8; }","tryCatchPattern":"try {\n  serializer.validate(value, byteBufferAccessor);\n} catch (MarshalException e) {\n  throw new DataCorruptionException(\"unexpected byte width for timestamp column\", e);\n}","preventionTips":["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"],"tags":["cassandra","serialization","timestamp","byte-size"],"backgroundTag":"type-mismatch","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}