apache/shardingsphere · error · SQLFeatureNotSupportedException

Wrong length `%d` of MYSQL_TYPE_TIME

Error message

Wrong length `%d` of MYSQL_TYPE_TIME

What it means

Thrown when a MySQL binary-protocol date value has an unexpected length byte: only 0 (zero date, itself rejected separately), 4 (date), 7 (datetime), and 11 (datetime with microseconds) are valid. Any other length means the binary value is malformed or the reader is misaligned. Note the message text says MYSQL_TYPE_TIME but is produced by the DATE reader in MySQLDateBinaryProtocolValue — a copy-paste wording issue.

Source

Thrown at database/protocol/dialect/mysql/src/main/java/org/apache/shardingsphere/database/protocol/mysql/packet/command/query/binary/execute/protocol/MySQLDateBinaryProtocolValue.java:52

    
    private static final long NANOS_PER_SECOND = 1_000_000_000L;
    
    @Override
    public Object read(final MySQLPacketPayload payload, final boolean unsigned) throws SQLException {
        int length = payload.readInt1();
        switch (length) {
            case 0:
                throw new SQLFeatureNotSupportedException("Can not support date format if year, month, day is absent.");
            case 4:
                return getTimestampForDate(payload);
            case 7:
                return getTimestampForDatetime(payload);
            case 11:
                Timestamp result = getTimestampForDatetime(payload);
                result.setNanos(payload.readInt4() * 1000);
                return result;
            default:
                throw new SQLFeatureNotSupportedException(String.format("Wrong length `%d` of MYSQL_TYPE_TIME", length));
        }
    }
    
    private Timestamp getTimestampForDate(final MySQLPacketPayload payload) {
        return Timestamp.valueOf(LocalDate.of(payload.readInt2(), payload.readInt1(), payload.readInt1()).atStartOfDay());
    }
    
    private Timestamp getTimestampForDatetime(final MySQLPacketPayload payload) {
        return Timestamp.valueOf(LocalDateTime.of(payload.readInt2(), payload.readInt1(), payload.readInt1(), payload.readInt1(), payload.readInt1(), payload.readInt1()));
    }
    
    @Override
    public void write(final MySQLPacketPayload payload, final Object value) {
        LocalDateTime dateTime;
        if (value instanceof LocalDate) {
            dateTime = ((LocalDate) value).atStartOfDay();
        } else {
            dateTime = value instanceof LocalDateTime ? (LocalDateTime) value : new Timestamp(((Date) value).getTime()).toLocalDateTime();

View on GitHub (pinned to e952770a21)

Solutions

  1. Ignore the 'TIME' wording — the failure is in the DATE/DATETIME binary reader; identify which column was being parsed
  2. Capture the binary resultset (e.g. with a proxy/Wireshark) and verify the length byte of each date value against the MySQL binary protocol
  3. Test the same query with useServerPrepStmts=false to bypass the binary protocol and confirm data integrity
  4. Report upstream with the server version and failing row if a standard server reproduces it
Defensive patterns

Strategy: try-catch

Try / catch

try {
    value = dateBinaryProtocolValue.read(payload, unsigned);
} catch (SQLFeatureNotSupportedException ex) {
    // length not in {0,4,7,11}: stream or data is corrupt; re-run the query over text protocol to confirm
    log.warn("binary date decode failed: {}", ex.getMessage());
    throw ex;
}

Prevention

When it happens

Trigger: MySQLDateBinaryProtocolValue.read() receives a length byte other than 0/4/7/11 — from a corrupted packet, a reader desynced after earlier fields, or a server/fork emitting a nonstandard encoding.

Common situations: Packet stream misalignment after a wrongly-parsed preceding column; connecting non-MySQL clients to the MySQL port; very new server versions changing binary date encoding.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/f42292c459206b30. Report an issue: GitHub.